【问题标题】:How to programatically resize a DrawingVisual?如何以编程方式调整 DrawingVisual 的大小?
【发布时间】:2020-12-08 20:57:47
【问题描述】:

所以,我是 WPF 绘图的新手。出于性能原因,我不得不从 ContentControl 和 UserControl 等常规控件切换到更轻量级的元素,例如 DrawingVisual。我正在开发一个图表应用程序,它可能在画布上最多有 1000 个元素,可以拖动、调整大小等。首先,使用 DrawingVisual 代替 Shape 更好吗? 其次,我的主要问题在这里。我正在向 Canvas 添加 DrawingVisual 元素:

public class SVisualContainer : UIElement
{
    // Create a collection of child visual objects.
    private VisualCollection _children;

    public SVisualContainer()
    {
        _children = new VisualCollection(this);
        _children.Add(CreateDrawingVisualRectangle());
    }

    // Create a DrawingVisual that contains a rectangle.
    private DrawingVisual CreateDrawingVisualRectangle()
    {
        DrawingVisual drawingVisual = new DrawingVisual();

        // Retrieve the DrawingContext in order to create new drawing content.
        DrawingContext drawingContext = drawingVisual.RenderOpen();

        // Create a rectangle and draw it in the DrawingContext.
        Rect rect = new Rect(new System.Windows.Point(160, 100), new System.Windows.Size(320, 80));
        drawingContext.DrawRectangle(System.Windows.Media.Brushes.LightBlue, null, rect);

        // Persist the drawing content.
        drawingContext.Close();

        return drawingVisual;
    }

    // Provide a required override for the VisualChildrenCount property.
    protected override int VisualChildrenCount
    {
        get { return _children.Count; }
    }



    // Provide a required override for the GetVisualChild method.
    protected override Visual GetVisualChild(int index)
    {
        if (index < 0 || index >= _children.Count)
        {
            throw new ArgumentOutOfRangeException();
        }

        return _children[index];
    }
}

在画布内:

public void AddStateVisual()
{
    var sVisual = new SVisualContainer();
    Children.Add(sVisual);
    Canvas.SetLeft(sVisual, 10);
    Canvas.SetTop(sVisual, 10);
}

如何通过代码动态增加 Rectangle 的大小?我已经尝试设置 Rectangle 的高度和宽度,但它不起作用,使用 ScaleTransform 进行处理,但这可能不是我想要的。我需要重新绘制矩形吗?谢谢!

【问题讨论】:

  • Drawingvisual 的重量比形状轻,但形状有宽度和高度,这听起来像是你的情况下的赢家。效率差异是否会成为问题取决于您的期望。我们的地图绘制软件允许用户绘制地形的轮廓形状。一种是“充满”树木的树林。树是一个用户控件,包含几个形状,一个阴影,并不完全简单。在 Visual Studio 中处于调试模式时,在我的机器上渲染大约一万棵树需要不到 3 秒的时间。我认为这是可以接受的,但也许您期望更快。
  • 这是很好的信息。如果渲染 10000 个 UserControls 只需要 3 秒,我认为可能比 UserControls 更轻的 Shapes 肯定符合我的要求。我仍然想知道如何调整 DrawingVisual 的大小以防万一。但是感谢您提供的信息!
  • 为什么 ScaleTransform 不适合你?
  • ScaleTransform 是否适合用户在画布中调整视觉对象大小的场景?我认为 ScaleTransform 用于缩放等,但如果我错了,请纠正我。例如,如果有一个 RectangleGeometry 视觉对象,其宽度为 100,高度为 100。并且用户拖动它的角,我如何使用 ScaleTransform 增加/减小大小?目前,我只是重绘 RectangleGeometry。
  • 你可以建立一个绘图或可写位图,如果事情发生变化,你可以重新绘制整个东西。在其他地方,我构建了一个高度测量图像作为可写位图,当我测量它时花了 29 毫秒。但是当您看到需要修复的实际问题时,我会担心优化。这些树是使用项目控件中的数据模板呈现的用户控件。很可能每棵树都比您需要的复杂。它们每个都包含三个路径和一个阴影。也许用户控件是矫枉过正的。相反,如果您只有一条路径,其中定义了一种几何图形,那会轻得多。

标签: wpf drawingcontext drawingvisual


【解决方案1】:

我最终在UIElement 中使用DrawingVisual,如问题所示,并在调整大小时不断重绘DrawingVisualUIElement.RenderSize 属性、UIElement.MeasureCore 方法和 UIElement.InvalidateMeasure 方法对此至关重要。这效果很好,性能可以接受。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-07-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-06-08
    相关资源
    最近更新 更多