WPF依赖项属性优先级 - 模板化父级

时间:2010-11-20 19:51:42

标签: wpf properties dependencies

list of sources for dependency property values中,除了相对优先级外,本地值是确定基值的最高优先级。
在本地值之后立即是模板化父级的模板属性 - 例如。用于在模板上下文中创建的控件的父ControlTemplate。

我的问题是这个 - 因为本地值被列为优先于模板属性,这是否意味着在模板中创建的控件上显式设置的属性值(本地值)优先于一个具有该模板中的属性触发器?这似乎是规则所暗示的,但在控件模板中使用触发器设置的属性似乎会覆盖(即更高优先级)模板中设置的本地值。

或者,优先级列表中的“本地值”是指仅在未在模板中创建的控件上设置的值 - 因此您无法通过模板中的触发器真正比较本地值和属性集之间的优先级父?

1 个答案:

答案 0 :(得分:4)

是的,优先级列表中的“本地值”仅指在模板外部的元素上设置的属性。优先列表的相关部分是4b:

  

4。 TemplatedParent模板属性。元素有一个   TemplatedParent,如果它被创建为   模板的一部分(ControlTemplate   或DataTemplate)。有关何时的详细信息   这适用,请参阅TemplatedParent   稍后在本主题中。内   模板,以下优先顺序   适用:

     

一个。来自TemplatedParent的触发器   模板。

     

湾财产集(通常通过   XAML属性)中   TemplatedParent模板。

模板中设置的属性值优先于模板中的触发器,并且这两个优先级低于本地值。

您可以通过调用DependencyPropertyHelper.GetValueSource并检查BaseValueSource属性来查看值的设置方式。在模板外部设置的值将具有“本地”源,而模板内部的值将具有“ParentTemplate”源。

将它们作为单独的源也意味着属性系统可以分别跟踪本地值和父模板值。如果您在具有模板值的属性上设置本地值,然后调用ClearValue,则它将恢复为模板设置的值。


以下示例演示了覆盖模板中值的本地值。使用下面的代码创建UserControl并将其添加到Window。它有一个蓝色矩形,当鼠标位于控件上方时,它会变为绿色。如果单击“设置”,代码将在矩形上设置一个本地值,该值将覆盖这两个值。如果单击“清除”,它将清除本地值并从模板中恢复值。您可以单击“显示”以查看当前值源(您需要使用键盘按下按钮以查看ParentTemplate,因为将鼠标悬停在按钮上将触发触发器)。

XAML:

<UserControl
    x:Class="WpfApplication1.UserControl1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
    <UserControl.Template>
        <ControlTemplate>
            <StackPanel Background="Transparent">
                <Button Click="Display_Click" Content="Display"/>
                <Button Click="Set_Click" Content="Set"/>
                <Button Click="Clear_Click" Content="Clear"/>
                <Rectangle Width="100" Height="100"
                           Fill="Blue" Name="PART_Rectangle"/>
            </StackPanel>
            <ControlTemplate.Triggers>
                <Trigger Property="IsMouseOver" Value="True">
                    <Setter TargetName="PART_Rectangle"
                            Property="Fill" Value="Green"/>
                </Trigger>
            </ControlTemplate.Triggers>
        </ControlTemplate>
    </UserControl.Template>
</UserControl>

代码隐藏:

public partial class UserControl1 : UserControl
{
    public UserControl1()
    {
        InitializeComponent();
    }

    public override void OnApplyTemplate()
    {
        base.OnApplyTemplate();
        rectangle = Template.FindName("PART_Rectangle", this) as Rectangle;
    }

    private Rectangle rectangle;

    private void Display_Click(object sender, RoutedEventArgs e)
    {
        var source = DependencyPropertyHelper.GetValueSource(
            rectangle, Rectangle.FillProperty);
        MessageBox.Show(string.Format("Value {0}; Source {1}",
            rectangle.Fill, source.BaseValueSource));
    }

    private void Set_Click(object sender, RoutedEventArgs e)
    {
        rectangle.Fill = Brushes.Red;
    }

    private void Clear_Click(object sender, RoutedEventArgs e)
    {
        rectangle.ClearValue(Rectangle.FillProperty);
    }
}