WPF:从frameworkelement派生的刷新类

时间:2011-08-12 21:01:33

标签: wpf custom-controls

它真的很奇怪。我有一些派生自框架元素的类。这是愚蠢的代码,因为我想让它变得更容易:P

public class Strange : FrameworkElement
{
    public DrawingVisual Visual;

    public Strange()
    {
        Visual = CreateDrawingVisualRectangle();
    }

    protected override Visual GetVisualChild(int index)
    {
        return Visual;
    }
    protected override int VisualChildrenCount
    {
        get
        {
            return 1;
        }
    }

    // Create a DrawingVisual that contains a rectangle.
    public DrawingVisual CreateDrawingVisualRectangle()
    {

        var drawingVisual = new DrawingVisual();

        DrawingContext drawingContext = drawingVisual.RenderOpen();
        var rect = new Rect(new Point(0, 0), new Size(100, 100));
        drawingContext.DrawRectangle(Brushes.Red, null, rect);
        drawingContext.Close();

        return drawingVisual;
    }
}

接下来我把这个类放到Grid上。

<Grid>
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="Auto"/>
        <ColumnDefinition Width="*"/>
    </Grid.ColumnDefinitions>
    <Button Click="Button_Click">Change Color</Button>
    <Test:Strange Grid.Column="1" x:Name="strange"/>
</Grid> 

 private void Button_Click(object sender, RoutedEventArgs e)
    {
        strange.Visual = strange.CreateDrawingVisualRectangle();
        var size = new Size(strange.ActualWidth, strange.ActualHeight);
        strange.Measure(size);
        strange.Arrange(new Rect(size));
        strange.UpdateLayout();
    }

当我按下Button时,Strange对象转到第一列(它在Grid的开头呈现)。我的项目中有更多逻辑,我需要刷新Strange对象,但它应该仍然在第二列(在它所在的位置)。

我做错了什么?

1 个答案:

答案 0 :(得分:4)

当你在对象上调用Arrange时,它会在你提供的位置重绘自身,相对于它的父对象。由于它的父级是网格,(0,0,size.Width,size.Height)会将它放在左上角。

要解决您的问题,而不是衡量和安排,您应该致电InvalidateMeasure

strange.Visual = strange.CreateDrawingVisualRectangle();
strange.InvalidateMeasure();

但是,我认为你正在接近这个问题。我想你想要做的是覆盖OnRender来绘制你的控件。它与您使用DrawingVisual的内容非常相似,只是您的FrameworkElement正在绘制内容:

protected override void OnRender(DrawingContext dc)
{            
    var rect = new Rect(new Point(0, 0), new Size(100, 100));
    dc.DrawRectangle(Brushes.Red, null, rect);
}

我假设您将使用一些DependencyProperty来控制Strange类的绘制方式。如果使用FrameworkPropertyMetadata.AffectsRender属性注册它们,它将自动重新绘制类。例如,这将允许您为Color对象设置Strange,并在设置属性时自动重绘:

public class Strange : FrameworkElement
{
    #region Color Dependency Property
    public static readonly DependencyProperty ColorProperty = 
      DependencyProperty.Register(
      "Color",
      typeof(Color),
      typeof(Strange),
      new FrameworkPropertyMetadata(Colors.Red, 
          FrameworkPropertyMetadataOptions.AffectsRender));

    public Color Color
    {
        get { return (Color)GetValue(ColorProperty); }
        set { SetValue(ColorProperty, value); }
    }
    #endregion 

    protected override void OnRender(DrawingContext dc)
    {            
        var rect = new Rect(new Point(0, 0), new Size(100, 100));
        dc.DrawRectangle(new SolidColorBrush(Color), null, rect);
    }
}