You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

WPF中如何通过代码动态调整DrawingVisual内矩形大小?附选型疑问

关于WPF中DrawingVisual的使用问题解答

嘿,作为WPF绘图新手,你能考虑到性能并切换到DrawingVisual真的很明智!先直接回答你的两个问题:

1. DrawingVisual是否比Shape更合适?

绝对是的!Shape类(比如Rectangle、Ellipse)属于FrameworkElement,它们自带了布局、样式、数据绑定等一系列WPF高级特性,但这些特性在你需要处理1000个可交互元素的场景下,会带来大量不必要的性能开销——每个Shape都要经历完整的WPF布局管线,内存占用也更高。

DrawingVisual是轻量级的Visual子类,它跳过了FrameworkElement的很多冗余逻辑,专注于图形渲染,内存占用低、渲染速度快,非常适合你这种需要大量绘制元素的绘图应用场景。所以你的选择完全正确!

2. 如何动态增大DrawingVisual中的矩形尺寸?

你之前尝试直接修改Rectangle的Width/Height无效,是因为你当前的代码是一次性绘制矩形的——调用drawingContext.Close()后,DrawingVisual的内容就固定了,没法直接编辑已绘制的图形。要动态调整,你需要存储图形的参数,在需要修改时重新绘制

下面是修改后的代码示例,我帮你重构了SVisualContainer类,让它支持动态调整矩形尺寸:

using System;
using System.Windows;
using System.Windows.Media;

public class SVisualContainer : UIElement {
    private VisualCollection _children;
    private DrawingVisual _drawingVisual;
    // 存储矩形的位置和尺寸参数,方便后续修改
    private Rect _rectangleBounds;

    public SVisualContainer() {
        _children = new VisualCollection(this);
        // 初始化矩形参数
        _rectangleBounds = new Rect(new Point(160, 100), new Size(320, 80));
        _drawingVisual = CreateDrawingVisual();
        _children.Add(_drawingVisual);
    }

    private DrawingVisual CreateDrawingVisual() {
        DrawingVisual visual = new DrawingVisual();
        // 使用using自动管理DrawingContext的生命周期
        using (DrawingContext dc = visual.RenderOpen()) {
            dc.DrawRectangle(Brushes.LightBlue, null, _rectangleBounds);
        }
        return visual;
    }

    // 提供一个公开方法,用于动态增大矩形尺寸
    public void EnlargeRectangle(double addWidth, double addHeight) {
        // 更新矩形参数
        _rectangleBounds.Width += addWidth;
        _rectangleBounds.Height += addHeight;
        // 重新绘制矩形
        using (DrawingContext dc = _drawingVisual.RenderOpen()) {
            dc.DrawRectangle(Brushes.LightBlue, null, _rectangleBounds);
        }
        // 触发控件重绘,确保界面更新
        InvalidateVisual();
    }

    // 也可以提供直接设置尺寸的方法
    public void SetRectangleSize(double width, double height) {
        _rectangleBounds.Width = width;
        _rectangleBounds.Height = height;
        using (DrawingContext dc = _drawingVisual.RenderOpen()) {
            dc.DrawRectangle(Brushes.LightBlue, null, _rectangleBounds);
        }
        InvalidateVisual();
    }

    protected override int VisualChildrenCount => _children.Count;

    protected override Visual GetVisualChild(int index) {
        if (index < 0 || index >= _children.Count) {
            throw new ArgumentOutOfRangeException(nameof(index));
        }
        return _children[index];
    }
}

之后你就可以在外部调用这个方法来动态调整尺寸了:

// 假设你已经实例化了sVisual
sVisual.EnlargeRectangle(50, 30); // 宽度增加50,高度增加30

为什么ScaleTransform不是最佳选择?

ScaleTransform是对整个Visual进行缩放,它会让矩形的所有部分(包括位置)按比例放大,如果你只是想保持矩形的左上角位置不变,单纯增大宽高,重新绘制的方式会更精准,也更符合你“调整大小”的需求。

另外,如果你后续需要实现拖拽功能,也可以用类似的思路:存储矩形的X/Y坐标,修改后重新绘制,这样比依赖Canvas的Left/Top属性更高效,因为你可以直接控制图形的原始位置,不需要经过Canvas的布局计算。

内容的提问来源于stack exchange,提问作者heapoverflow

火山引擎 最新活动