Приоритет свойства Trigger vs. Dependency

У меня вопрос о приоритете значения свойства зависимости. Мой .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>

In my Codebehind I created the dependency property 'BG' like:

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 в коде?


person dabuntu    schedule 09.06.2015    source источник
comment
Привязка Background="{Binding BG,Mode=TwoWay}" не устанавливает значение свойства BG. Здесь BG является источником привязки, а не целью.   -  person Clemens    schedule 09.06.2015


Ответы (2)


Ваше изменение кода фактически считается локальным изменением. С вашей связанной страницы в MSDN:

Местное значение. Локальное значение может быть установлено с помощью удобства свойства "оболочки", которое также равнозначно настройке в качестве атрибута или элемента свойства в XAML, или путем вызова API SetValue с использованием свойства определенного экземпляра. Если вы устанавливаете локальное значение с помощью привязки или ресурса, каждый из них действует в соответствии с приоритетом, как если бы было установлено прямое значение.

Я выделил соответствующую часть, в которой говорится, что вызов SetValue, как вы сделали (через ваше свойство BG CLR), приведет к изменению Local. Поскольку локальное изменение имеет более высокий приоритет, чем Trigger, оно имеет приоритет над значением Trigger.

person Sheridan    schedule 09.06.2015
comment
Спасибо за ваш быстрый ответ :), я уже читал это, но, возможно, я не понимаю... Установка значения свойства зависимости по умолчанию в PropertyMetada - это более или менее вызов SetValue свойства не так ли? И если это так, то Триггер с самого начала будет иметь более низкий приоритет. Мне интересно, является ли настройка метаданных черным цветом чем-то другим, чем вызов SetValue? - person dabuntu; 09.06.2015
comment
Посмотрите еще раз... значение свойства по умолчанию стоит последним в списке: Значение по умолчанию из метаданных свойства зависимостей. Следовательно, все остальное может перекрыть его. - person Sheridan; 09.06.2015
comment
О, я должен был перечитать это, там все ясно... Большое спасибо! Есть ли обходной путь, чтобы я мог снова активировать триггер? - person dabuntu; 09.06.2015

Вместо

BG = Brushes.Green;

который устанавливает локальное значение с более высоким приоритетом, чем триггер, вы можете написать

SetCurrentValue(BGProperty, Brushes.Green);

Из MSDN :

... Метод SetCurrentValue изменяет действующее значение свойства, но существующие триггеры, привязки данных и стили будут продолжать работать.

person Clemens    schedule 09.06.2015
comment
Спасибо за ваш ответ :), я намеревался изменить источник свойства. Когда я нажимаю кнопку, я бы хотел, чтобы фон сетки был зеленым, если мышь отсутствует, и синим, если мышь закончилась. Поэтому я могу сказать, что либо я могу изменить свой исходный код в коде позади и потерять свой триггер, либо я могу изменить свойство с помощью SetCurrentValue(), но не могу изменить фон на зеленый в долгосрочной перспективе. это правильно? - person dabuntu; 09.06.2015