WPF 是否继承了附加依赖属性 "expensive"?

Are WPF Inherited Attached Dependency properties "expensive"?

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

解释一下:绘图的一些方面(例如线宽、字体大小等)是用户可配置的,但 受缩放级别影响。我很快发现仅仅将形状的 StrokeThickness 绑定到配置值会导致问题。如果用户放大或缩小 canvas 方式,厚度就会改变。我希望它保持不变。

所以我选择了一个解决方案,而不是将我的形状绑定到一组全局的、瞬态的 "Live" 设置,这些设置源自配置的设置和当前的缩放比例。当用户放大或缩小我的 canvas 时,代码隐藏会更改这些实时设置。

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 .../>

这一切都很好,但是将我的所有对象绑定到一个全局对象的事情让我很困扰。如果必须的话,我可以继续使用它,但我不介意更干净的东西。

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

不过我可能有很多很多形状。所以我想知道这会如何影响性能。 WPF 通过包含继承来传播这样一个 属性 的开销有多大?

我已经调试了一些附加属性的工作原理,看起来当附加的继承 属性 发生变化时,继承上下文中的每个项目都会收到有关它的通知。所以看起来这确实可能非常昂贵。我不想让我的缩放延迟或任何东西。

有人遇到过此类问题吗?这个有什么需要注意的吗

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

使用此鼠标滚轮处理程序:

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