简体   繁体   English

WPF继承的附加依赖项属性是否“昂贵”?

[英]Are WPF Inherited Attached Dependency properties “expensive”?

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. 我想知道将当前方法从使用全局临时设置对象更改为使用继承的附加属性的影响。

To explain: A few aspects of the drawing (eg 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. 我很快发现,仅将形状的StrokeThickness绑定到配置的值会引起问题。 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;

}

Binding: 捆绑:

<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. 如果可以的话,我可以留下来,但我不介意更清洁的东西。

So I wondered about an approach that used WPF Property Inheritance instead; 因此,我想知道一种使用WPF属性继承的方法。 I could, alternately register properties like this as inherited attached properties on my canvas ("ShapeCanvas"). 我可以将这样的属性作为继承的附加属性注册到我的画布(“ ShapeCanvas”)上。 Then my shapes could bind to "ShapeCanvas.LineWidth" and not need to rely on the existence of some global settings object. 然后,我的形状可以绑定到“ ShapeCanvas.LineWidth”,而不必依赖于某些全局设置对象的存在。

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? WPF通过包含继承传播这样的属性有多昂贵?

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. 这是值得关注的事情。

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: 这是一个非常简单的示例,说明如何变换路径的几何图形而不是路径元素本身,从而避免了重新调整其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>

with this MouseWheel handler: 使用此MouseWheel处理程序:

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;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM