WPF:创建具有可变间距的可捕捉网格线

时间:2010-01-08 16:13:00

标签: wpf grid

我目前正在创建一个类似MSPaint的WPF应用程序,并且正在努力实现可抢占的网格。

对于VisualBrush和Rectangle,网格的绘制没有问题,但问题是这些线条纯粹是用于外观并且不能轻易更改(例如,当触发捕捉到特定线时突出显示)。

我的另一个想法是有一个2 Canvas解决方案,其中1 Canvas用于元素,一个Canvas(位于另一个之上)包含所有网格线。但是我觉得这意味着性能受到了很大影响。

有没有其他可能的方法来实现这种功能?

2 个答案:

答案 0 :(得分:2)

双面板方法与DrawingContext

的效率考虑因素

我有个好消息:你对重大的性能影响是错误的。即使您使用单个对象作为网格线,您的双画布构思也几乎是最佳的。这是因为WPF使用保留模式渲染:当您创建画布时,其上的所有内容都将序列化为本机级别的紧凑结构。只有在以某种方式更改网格线时才会更改,例如更改网格间距。在所有其他时间,性能将与最快可能的托管代码方法无法区分。

尼古拉斯描述的使用DrawingContext可以略微提升性能。

更简单,更有效的解决方案

也许更好的方法是在网格画布上绘制单独的线条是使用两个平铺的可视画笔(一个水平,一个垂直)来绘制所有未加工的线条,然后在代码隐藏中添加Rectangle(s)把你正在捕捉的线条变成白色。

此技术的主要优点是您的网格可以有效无限,因此无需计算正确的网格线数量,然后每次窗口调整大小或缩放更改时更新。您还只涉及三个UIElements,另外还有一个目前正在使用的每个网格线。对我来说,跟踪网格线的集合似乎也比较清晰。

您想要使用两个可视画笔的原因是绘图效率更高:绘制垂直线的画笔在垂直方向上拉伸到一个很大的距离(例如double.MaxValue / 2),因此GPU只获得一个绘图每条垂直线呼叫,水平方向相同。做双向平铺的效率要低得多。

装配层

由于您询问了替代方案,另一种可能性是将AdornerAdornerLayer用于上述任何解决方案,而不是使用例如网格或包含Canvas来堆叠画布。对于类似Paint的应用程序,这很好,因为装饰图层可以位于图形图层之上,但装饰者仍然可以附加到正在显示的单个项目上。

答案 1 :(得分:1)

您可以考虑使用DrawingContext内的OnRender绘制网格。以这种方式绘制不会在视觉树中引入新的UIElements,这有助于提高性能。在某些方面,它类似于您目前使用VisualBrush所做的事情,它也不会为每个副本创建新的UI元素。

但是,由于您实际上将单独绘制每一行而不是复制单行的外观,因此您将能够突出显示参与捕捉的网格线而不更改那些不相应的颜色。

如果您打算沿着这条路走下去,请务必查看GuidelineSet以找到您的指引线(更多详情here),因为您可能希望拥有引导线捕捉设备的像素,以便它们绘制得很清晰。