以下のようにカスタム コントロールを定義しました。Generic.xaml ファイルには、「cvRoot」という名前のキャンバスを含むテンプレートのみが含まれています。
依存関係プロパティの 1 つが変更されたときに、コントロールを適切に再レンダリングすることができません。アプリケーションで使用すると描画される場合がありますが、測定しようとすると、常にサイズがゼロになります。コントロールを適切に配置するためにサイズを取得する必要があるため、これは非常にイライラします。
オプションを AffectsRender に設定して Dependency Property register メソッドで FrameworkPropertyMetadata を使用しようとしましたが、これは何が起こるかを変えません。また、各プロパティの Callback で InvalidateVisual を試してみましたが、喜びはありませんでした。
私は本当にここで髪を引っ張っています、何かアイデアはありますか?
namespace GraphControls
{
public class Marker : Control
{
private Canvas cvRoot = null;
private static Action EmptyDelegate = delegate() { };
static Marker()
{
DefaultStyleKeyProperty.OverrideMetadata(typeof(Marker), new FrameworkPropertyMetadata(typeof(Marker)));
}
public override void OnApplyTemplate()
{
base.OnApplyTemplate();
cvRoot = GetTemplateChild("cvRoot") as Canvas;
}
protected override void OnRender(DrawingContext drawingContext)
{
base.OnRender(drawingContext);
cvRoot.Children.Clear();
// Text
//
TextBlock tb = new TextBlock();
tb.Text = Text;
tb.FontSize = MarkerFontSize;
tb.Foreground = TextColour;
tb.Measure(new Size(Double.PositiveInfinity, Double.PositiveInfinity));
// Background Ellipse
//
Ellipse el = new Ellipse();
el.Width = tb.DesiredSize.Height;
el.Height = tb.DesiredSize.Height;
el.Fill = MarkerFill;
// Add to Canvas and reposition
//
cvRoot.Children.Add(el);
cvRoot.Children.Add(tb);
Canvas.SetLeft(tb, (el.Width / 2) - (tb.DesiredSize.Width / 2));
Canvas.SetTop(tb, (el.Height / 2) - (tb.DesiredSize.Height / 2));
// Resize the owning Canvas so that external Measures work
//
cvRoot.Width = el.Width;
cvRoot.Height = el.Height;
}
public static DependencyProperty TextProperty = DependencyProperty.Register("Text", typeof(string), typeof(Marker),
new PropertyMetadata("X", new PropertyChangedCallback(OnGenericDependencyPropertyChanged)));
public static DependencyProperty MarkerFontSizeProperty = DependencyProperty.Register("MarkerFontSize", typeof(double), typeof(Marker),
new PropertyMetadata(12D, new PropertyChangedCallback(OnGenericDependencyPropertyChanged)));
public static DependencyProperty MarkerFillProperty = DependencyProperty.Register("MarkerFill", typeof(Brush), typeof(Marker),
new PropertyMetadata(new SolidColorBrush(Colors.Black), new PropertyChangedCallback(OnGenericDependencyPropertyChanged)));
public static DependencyProperty TextColourProperty = DependencyProperty.Register("TextColour", typeof(Brush), typeof(Marker),
new PropertyMetadata(new SolidColorBrush(Colors.White), new PropertyChangedCallback(OnGenericDependencyPropertyChanged)));
public string Text
{
get { return (string)GetValue(TextProperty); }
set { SetValue(TextProperty, value); }
}
public double MarkerFontSize
{
get { return (double)GetValue(MarkerFontSizeProperty); }
set { SetValue(MarkerFontSizeProperty, value); }
}
public Brush MarkerFill
{
get { return (Brush)GetValue(MarkerFillProperty); }
set { SetValue(MarkerFillProperty, value); }
}
public Brush TextColour
{
get { return (Brush)GetValue(TextColourProperty); }
set { SetValue(TextColourProperty, value); }
}
private static void OnGenericDependencyPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
((Marker)d).Dispatcher.Invoke(DispatcherPriority.Render, EmptyDelegate);
}
protected override Size MeasureOverride(Size constraint)
{
Size retval = new Size();
// Handle the template not being called yet
//
if (cvRoot != null)
{
cvRoot.Measure(constraint);
retval = cvRoot.DesiredSize;
}
return retval;
}
}
}