我有一个定义如下的自定义控件,Generic.xaml 文件仅包含一个模板,其中包含一个名为“cvRoot”的画布。
当依赖项属性之一发生更改时,我无法让控件正确地重新呈现自身。虽然当我在应用程序中使用它时它可能会绘制,但当我尝试测量它时,我总是得到一个零尺寸。这非常令人沮丧,因为我需要获得正确对齐控件的大小。
我尝试在 Dependency Property register 方法中使用 FrameworkPropertyMetadata,并将选项设置为 AffectsRender,但这不会改变发生的情况。我还在 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;
}
}
}