WPF继承的附加依赖项属性是否“昂贵”? [英] Are WPF Inherited Attached Dependency properties "expensive"?

查看:112
本文介绍了WPF继承的附加依赖项属性是否“昂贵”?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个可以正常工作的应用程序,可以在可缩放的画布上绘制形状和图像。我想知道将当前方法从使用全局临时设置对象更改为使用继承的附加属性的效果。

I've got a working app that draws shapes and images on a zoomable canvas. I'm wondering about the effects of changing my current approach from using a global, transient settings object to using inherited attached properties.

要说明:图纸的一些方面(例如,线宽,字体大小等)可由用户配置,但 也会受缩放级别的影响。我很快发现,仅将形状的StrokeThickness绑定到配置的值会引起问题。如果用户放大或缩小画布,则厚度会更改。我希望它保持恒定。

To explain: A few aspects of the drawing (e.g. line widths, font sizes, etc) are user-configurable but are also affected by zoom level. I quickly found that merely binding, say, the StrokeThickness of my shapes to a configured value caused problems. If the user zoomed the canvas way in or out, the thickness changed. I wanted it to stay constant.

所以我选择了一个解决方案,该解决方案将我的形状绑定到一个全局的,瞬态的实时设置集,这些设置来自配置设置以及当前的缩放比例。当用户放大或缩小我的画布时,后面的代码将更改这些实时设置。

So I chose up with a solution that instead bound my shapes to a global, transient set of "Live" settings derived from the configured settings and the current zoom scale. The code-behind changes these live settings as the user zooms my canvas in or out.

private void UpdateScaledSizesAfterZoom()
{
    // Get the scale from the canvas' scale transform. 

    if (!(Scene.LayoutTransform is ScaleTransform st))
        return;

    var div = st.ScaleX > 0 ? st.ScaleX : 1; 

    // Update all live settings with the new scale.

    LiveSettings.LineWidth       = Settings.LineWidth/ div;
    LiveSettings.FontSize        = Settings.FontSize / div;

}

绑定:

<Path StrokeThickness="{Binding Source={x:Static LiveSettings.Default}, Path=LineWidth}" Data=... blah blah blah .../>

这一切都足够好,但是将我的所有对象都绑定到全局对象的事情让我很烦。

This all works well enough but something about tying all my objects to a global object just plain bothers me. I can stay with it if I must but I wouldn't mind something cleaner.

所以我想知道一种使用WPF属性继承的方法;我可以使用它。我可以交替地将这样的属性注册为画布上的 继承的附加 属性( ShapeCanvas)。然后,我的形状可以绑定到 ShapeCanvas.LineWidth,而不必依赖于某些全局设置对象的存在。

So I wondered about an approach that used WPF Property Inheritance instead; I could, alternately register properties like this as inherited attached properties on my canvas ("ShapeCanvas"). Then my shapes could bind to "ShapeCanvas.LineWidth" and not need to rely on the existence of some global settings object.

但是我可能有很多很多形状。所以我想知道这可能会如何影响性能。 WPF通过遏制继承传播这样的属性有多昂贵?

However I might have many, many shapes. So I am wondering about how this might affect performance. How expensive is it for WPF to propagate a property like this through containment inheritance?

我已经调试了一些附加属性的工作方式,并且看起来当附加属性继承时属性更改时,实际上继承上下文中的每个项目都会收到通知。因此,看来这确实是非常昂贵的。我不想让缩放变得迟钝或什么。

I've already debugged some of how attached properties work and it appears that when an attached inherited property changes, literally every item in the inheritance context gets notified about it. So it seems like this could be quite expensive indeed. I wouldn't want to make my zooming laggy or anything.

有人在处理此类问题上有经验吗?

Does anyone have any experience with such issues? Is this something to be concerned about.

推荐答案

这是一个非常简单的示例,说明了如何变换路径的几何图形而不是Path元素本身,从而无需重新调整其StrokeThickness:

Here is a very simple example of how to transform the Geometry of a Path instead of the Path element itself, which avoids the need to re-scale its StrokeThickness:

<Window.Resources>
    <MatrixTransform x:Key="GeometryTransform"/>
</Window.Resources>
<Canvas Background="Transparent" MouseWheel="Canvas_MouseWheel">
    <Path Fill="Yellow" Stroke="Blue" StrokeThickness="3">
        <Path.Data>
            <PathGeometry Figures="M100,50 L150,100 100,150 50,100Z"
                          Transform="{StaticResource GeometryTransform}"/>
        </Path.Data>
    </Path>
</Canvas>

使用此MouseWheel处理程序:

with this MouseWheel handler:

private void Canvas_MouseWheel(object sender, MouseWheelEventArgs e)
{
    var transform = (MatrixTransform)Resources["GeometryTransform"];
    var matrix = transform.Matrix;
    var scale = e.Delta > 0 ? 1.1 : 1 / 1.1;
    var pos = e.GetPosition((IInputElement)sender);
    matrix.ScaleAt(scale, scale, pos.X, pos.Y);
    transform.Matrix = matrix;
}

这篇关于WPF继承的附加依赖项属性是否“昂贵”?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆