【问题标题】:Change the properties of a local class that draws on DrawingVisual更改在 DrawingVisual 上绘制的本地类的属性
【发布时间】:2014-08-03 09:00:07
【问题描述】:

我定义了一个派生自FrameworkElementDrawing 类。我正在使用它来绘制DrawingVisual。在我的XAML 中,我已经包含了这个本地类。

现在我的问题是如何将此类的属性绑定到变量,或者我什至如何更改它们?

例如,假设我想更改 width 属性。我在XAML 中添加了Button,并尝试更改width,但没有任何反应。

所有必需的代码如下:

<Window x:Class="Geom.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:geom="clr-namespace:Geom"
        Title="MainWindow" Height="350" Width="525">
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="*"/>
            <RowDefinition Height="100"/>
        </Grid.RowDefinitions>
        <Canvas Width="0" Height="0">
            <geom:Drawing x:Name="Drawing" />
        </Canvas>
        <Button Grid.Row="1" Content="Change" Click="ButtonBase_OnClick"/>
    </Grid>
</Window>


public class Drawing : FrameworkElement
{
    private readonly VisualCollection _visuals;
    public int width { get; set; }

    public Drawing()
    {
        RenderOptions.SetEdgeMode(this, EdgeMode.Aliased);
        _visuals = new VisualCollection(this);

        var geometryGroup = new GeometryGroup();
        width = 50;
        var depth = 50;
        var x = 50;
        var y = 50;
        var rect = new Rect(x, y , width, depth);
        var rectGeom = new RectangleGeometry(rect);
        geometryGroup.Children.Add(rectGeom);
        geometryGroup.Freeze();

        var drawingVisual = new DrawingVisual();
        using (var dc = drawingVisual.RenderOpen())
        {
            dc.DrawGeometry(Brushes.Blue, null, geometryGroup);
        }
        _visuals.Add(drawingVisual);
    }

    protected override Visual GetVisualChild(int index)
    {
        return _visuals[0];
    }

    protected override int VisualChildrenCount
    {
        get
        {
            return 1;
        }
    }
}


public partial class MainWindow
{
    public MainWindow()
    {
        InitializeComponent();
    }

    private void ButtonBase_OnClick(object sender, RoutedEventArgs e)
    {
        Drawing.width = 10;
    }
}

【问题讨论】:

  • 您必须在 DrawingContext 上重新绘制视觉效果才能看到更改。
  • 你能解释一下吗?我还为宽度定义了一个Dependency Property。并试图像这样&lt;geom:Drawing WProperty="10" x:Name="Drawing" /&gt; 改变宽度,它仍然没有工作。你能告诉我如何在答案中重绘。谢谢。

标签: c# wpf xaml drawingvisual


【解决方案1】:

要让 DrawingVisual 刷新,您必须使用新值在它的 drawingContext 上重新绘制视觉对象

因此,如果您设置宽度,则必须在其绘图上下文上重新绘制视觉对象。将您的代码更改为:

public class Drawing : FrameworkElement
{
    private readonly VisualCollection _visuals;

    private int width;
    public int VisualWidth
    {
        get { return width; }
        set
        {
            width = value;
            RefreshDrawing();
        }
    }

    public Drawing()
    {
        RenderOptions.SetEdgeMode(this, EdgeMode.Aliased);
        _visuals = new VisualCollection(this);

        var geometryGroup = new GeometryGroup();
        width = 50;
        DrawingVisual drawingVisual = new DrawingVisual();
        RefreshDrawing(drawingVisual);
        _visuals.Add(drawingVisual);
    }

    private void RefreshDrawing(DrawingVisual drawingVisual = null)
    {
        var geometryGroup = new GeometryGroup();
        var rect = new Rect(50, 50, VisualWidth, 50);
        var rectGeom = new RectangleGeometry(rect);
        geometryGroup.Children.Add(rectGeom);
        geometryGroup.Freeze();

        drawingVisual = drawingVisual ?? (DrawingVisual)GetVisualChild(0);
        using (var dc = drawingVisual.RenderOpen())
        {
            dc.DrawGeometry(Brushes.Blue, null, geometryGroup);
        }
    }

    protected override Visual GetVisualChild(int index)
    {
        return _visuals[0];
    }

    protected override int VisualChildrenCount
    {
        get
        {
            return 1;
        }
    }
}

从按钮点击处理程序中设置 VisualWidth

Drawing.VisualWidth = 10;

【讨论】:

  • 谢谢先生,这对我很有帮助。
  • 不客气,瓦希德。如果您想了解更多关于DrawingVisuals 的信息,请参阅精彩文章here。此外,还附有样品。
  • 顺便问一下,我走对了吗?使用GeometryGroup 并在DrawingVisual 上绘图是我在WPF 中绘制数百个几何图形的最有效方式吗?我在这里问是因为这个问题太笼统了,无法在 SO 上发布,我发现您对此非常了解。谢谢。
  • 如果只是感兴趣的矩形,可以直接用drawingContext.DrawRectangle方法画出来。还有一些简单形状的直接方法,您可以使用DrawEllipseDrawLine 等。但是当形状变得复杂时,DrawGeometry 是一种方法。
  • 我个人更喜欢绘制 1000 个单独的矩形,因为对于视觉上的任何变化,您都必须重新绘制它们。假设您想更改一个矩形的宽度,但如果它们是 GeometryGroup 的一部分,那么要刷新 1 个矩形,您必须重新绘制所有矩形,但不能使用第二种方法。此外,如果您同时尝试这两种方法,您会发现第二种方法的渲染速度比第一种方法快。
猜你喜欢
  • 2015-11-29
  • 1970-01-01
  • 2017-06-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-05-30
  • 2016-07-11
相关资源
最近更新 更多