WPF:刷新从frameworkelement派生的类

发布于 2024-11-29 21:38:28 字数 1658 浏览 0 评论 0原文

它的工作原理真的很奇怪。我有一些从框架元素派生的类。这是愚蠢的代码,因为我想让它变得更容易: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.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();
    }

当我按下按钮时,奇怪的对象转到第一列(它在网格的开头呈现)。我的项目中有更多逻辑,我需要刷新奇怪的对象,但它应该仍在第二列中(在原来的位置)。

我做错了什么?

It works realy strange. I have some class derived from the framework element. It is stupid code because I want to make it easier :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;
    }
}

Next I put this class to the 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();
    }

When I pressed the Button, the Strange object went to the first column (it is rendered at the begining of the Grid). I have more logic in my project and I need to refresh Strange object, but it should be still in the second column (in the place where it was).

What I did wrong?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

初见终念 2024-12-06 21:38:28

当您对对象调用 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 属性注册它们,它将自动导致类被重绘。例如,这将允许您为 Strange 对象设置 Color,并且当您设置该属性时它将自动重绘:

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);
    }
}

When you call Arrange on the object, it is redrawing itself at the location you provide, relative to its parent. Since its parent is the grid, (0,0,size.Width,size.Height) will put it in the upper-left hand corner.

To fix your immediate problem, instead of measuring, and arranging, you should just call InvalidateMeasure:

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

However, I think you are approaching this problem slightly wrong. I think what you want to do is to override OnRender to draw your control. It is very similar to what you're doing with the DrawingVisual, except your FrameworkElement is what is being drawn:

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

I assume that you would have some DependencyProperty's that you are using to control how your Strange class is drawn. If you register them with the FrameworkPropertyMetadata.AffectsRender property, it will automatically cause the class to be redrawn. For instance, this will allow you to set a Color for the Strange object, and it will automatically get redrawn when you set the property:

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);
    }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文