触发器与依赖关系 属性 优先级

Trigger vs. Dependency Property precendence

我对依赖项 属性 值的优先级有疑问。 我的 .xaml 如下所示:

<Window x:Class="WpfTests.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local ="clr-namespace:WpfTests"
    Title="MainWindow" Height="350" Width="525">
<Window.Style>
    <Style>
        <!--<Setter Property="Canvas.Background" Value="Gray"/>-->
        <Style.Triggers>
            <Trigger Property="local:MainWindow.IsMouseOver" Value="True">
                <!--<Setter Property="local:LeistenPfeil.Symbolfarbe" Value="Red"/>-->
                <Setter Property="local:MainWindow.Cursor" Value="Hand" />
                <Setter Property="local:MainWindow.BG" Value="Blue"/>
            </Trigger>
        </Style.Triggers>
    </Style>
</Window.Style>

<Grid Background="{Binding BG,Mode=TwoWay}">
    <Button Content="ChangeBG" HorizontalAlignment="Center" VerticalAlignment="Center" Click="OnClick"/>
</Grid>

在我的代码隐藏中,我创建了依赖项 属性 'BG',例如:

public partial class MainWindow : Window
{
    public Brush BG
    {
        get { return (Brush)GetValue(BGProperty); }
        set { SetValue(BGProperty, value); }
    }

    // Using a DependencyProperty as the backing store for BG.  This enables animation, styling, binding, etc...
    public static readonly DependencyProperty BGProperty =
        DependencyProperty.Register("BG", typeof(Brush), typeof(MainWindow), new PropertyMetadata(Brushes.Black));


    public MainWindow()
    {
        InitializeComponent();
        this.DataContext = this;
    }

    private void OnClick(object sender, RoutedEventArgs e)
    {
        BG = Brushes.Green;
    }
}

因此,启动时背景设置为黑色(DP 的默认设置)。当鼠标悬停时,背景变为蓝色。当涉及到我的代码隐藏中 BG-属性 的更改时,触发器确实起作用,但它对网格背景的影响消失了。 我已经在 MSDN 上阅读了这篇文章: https://msdn.microsoft.com/en-us/library/ms743230%28v=vs.110%29.aspx

我理解的问题是:为什么触发器在 BG-属性 具有其默认值时起作用,而当它在后面的代码中更改时却不起作用? => 背景的最高优先级是网格的本地背景绑定,那么为什么触发器会起作用?

在代码隐藏中更改 BG-属性 后,如何让触发器再次工作?

您的代码更改实际上被视为本地更改。从您在 MSDN 上的链接页面:

Local value. A local value might be set through the convenience of the "wrapper" property, which also equates to setting as an attribute or property element in XAML, or by a call to the SetValue API using a property of a specific instance. If you set a local value by using a binding or a resource, these each act in the precedence as if a direct value was set.

我突出显示了相关部分,指出像您那样调用 SetValue(通过您的 BG CLR 属性)将导致 Local 改变。由于 Local 更改的优先级高于 Trigger,它否决了 Trigger 值。

而不是

BG = Brushes.Green;

设置一个局部值比触发器更高的优先级,你可以这样写

SetCurrentValue(BGProperty, Brushes.Green);

来自MSDN

... The SetCurrentValue method changes the effective value of the property, but existing triggers, data bindings, and styles will continue to work.