微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

如何在Path.Data中使用TemplateBinding?

如何解决如何在Path.Data中使用TemplateBinding?

如何将Path.Data中的属性绑定到TemplateBinding?我注意到在下面的示例中,属性SegmentColorstrokeThickness的设置和更新正确,但属性TargetPoint却没有正确设置和更新。进一步的测试似乎可以确认问题似乎与嵌套在Path.Data元素中的属性有关。以下代码试图简化为自定义控件创建模板时遇到的上下文。

C#:

public class TestProgressBar : ProgressBar
{
    public Brush SegmentColor
    {
        get { return (Brush)GetValue(SegmentColorProperty); }
        set { SetValue(SegmentColorProperty,value); }
    }

    public double strokeThickness
    {
        get { return (double)GetValue(strokeThicknessProperty); }
        set { SetValue(strokeThicknessProperty,value); }
    }

    public Point TargetPoint
    {
        get { return (Point)GetValue(TargetPointProperty); }
        set { SetValue(TargetPointProperty,value); }
    }

    public static readonly DependencyProperty strokeThicknessProperty =
        DependencyProperty.Register(nameof(strokeThickness),typeof(double),typeof(TestProgressBar),new PropertyMetadata());

    public static readonly DependencyProperty SegmentColorProperty =
        DependencyProperty.Register(nameof(SegmentColor),typeof(Brush),new PropertyMetadata(new SolidColorBrush(Colors.Red)));

    public static readonly DependencyProperty TargetPointProperty =
        DependencyProperty.Register(nameof(TargetPoint),typeof(Point),new PropertyMetadata());
}

Xaml:

<c:TestProgressBar strokeThickness="15"
                   TargetPoint="100,0">
    <c:TestProgressBar.Style>
        <Style targettype="{x:Type c:TestProgressBar}">
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate targettype="{x:Type c:TestProgressBar}">
                        <Grid>
                            <Path
                                  stroke="{TemplateBinding SegmentColor}"
                                  strokeThickness="{TemplateBinding strokeThickness}"
                                  Width="100" Height="100">
                                <Path.Data>
                                    <PathGeometry>
                                        <Pathfigure>
                                            <Linesegment Point="{TemplateBinding TargetPoint}"/>
                                        </Pathfigure>
                                    </PathGeometry>
                                </Path.Data>
                            </Path>
                        </Grid>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>
    </c:TestProgressBar.Style>
</c:TestProgressBar>

解决方法

问题是关于TemplateBindingdo not work on properties Freezables)的鲜为人知的细节。实际上,正如您在其继承层次结构中看到的,LineSegment是间接从Freezable派生的。

Object-> DispatcherObject-> DependencyObject-> Freezable -> Animatable-> PathSegment-> LineSegment

但是,Path无效,这就是其属性上的TemplateBinding起作用的原因。由于模板绑定只是Binding的优化的但受限制的版本,因此您可以始终use its binding syntax equivalent不受任何限制,并且可以在{{1} } s。

Freezable

请注意,此处<LineSegment Point="{Binding TargetPoint,RelativeSource={RelativeSource TemplatedParent},Mode=OneWay}"/> 设置为Mode,以指出OneWay始终是单向的,这等效于TemplateBinding,但是绑定更强大,并支持任何绑定模式。

我使用的是只读依赖项属性,因此该问题无法链接到TwoWay绑定问题(因为我很难做到TemplateBinding的情况)。

依赖项属性声明必须是只读的,但这不会使依赖项属性本身成为只读,这是通过声明依赖项属性键并使用Binding方法来完成的。

,

似乎在Path.Data中使用TemplateBindings会导致此问题。将其替换为TemplatedParent绑定可解决此问题:

<LineSegment Point="{Binding TargetPoint,RelativeSource={RelativeSource TemplatedParent}}"/>

不过,我不能完全解释为什么。在我的原始代码中,我使用的是只读依赖项属性,因此该问题无法链接到TwoWay绑定问题(因为我对TemplateBinding很难做到)。

我知道,使用TemplatedParent进行绑定是在运行时评估的,而不是TemplateBinding的编译时,因此也许可以通过某些方式来修复绑定。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。