DataTrigger does not change Text property

2019-01-07 00:39发布

问题:

I'm attempting to use a data-trigger on a style to change a property.

In compliance with the "Minimal, Complete and Verifiable Example" requirements...

To reproduce, first create a WPF application in Visual Studio.

Within the App.xaml.cs :

using System.ComponentModel;
using System.Windows;

namespace Foo{
/// <summary>
/// Interaction logic for App.xaml
/// </summary>
public partial class App : Application, INotifyPropertyChanged {
        private bool _clicked;
        public bool Clicked {
            get { return this._clicked; }
            set {
                this._clicked = value;
                this.PropertyChanged?.Invoke(
                    this, new PropertyChangedEventArgs( "Clicked" ) );
            }
        }
        public event PropertyChangedEventHandler PropertyChanged;
    }
}

Within the MainWindow.xaml :

<Window
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:lib="clr-namespace:System;assembly=mscorlib"
    xmlns:local="clr-namespace:Foo"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    mc:Ignorable="d" x:Class="Foo.MainWindow"
    Title="MainWindow" Height="350" Width="525">
    <Window.Resources>
        <lib:Boolean x:Key="True">True</lib:Boolean>
    </Window.Resources>
    <Grid>
        <Button x:Name="button" Click="button_Click">
            <Viewbox>
                <TextBlock Text="Unclicked">
                    <TextBlock.Style>
                        <Style TargetType="{x:Type TextBlock}">
                            <Style.Triggers>
                                <DataTrigger
                                        Binding="{Binding
                                            Clicked,
                                            Source={x:Static Application.Current}}"
                                            Value="{StaticResource True}">
                                    <Setter Property="Text" Value="Clicked" />
                                </DataTrigger>
                            </Style.Triggers>
                        </Style>
                    </TextBlock.Style>
                </TextBlock>
            </Viewbox>
        </Button>
    </Grid>
</Window>

Within the MainWindow.xaml.cs -

using System.Windows;

namespace Foo{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window {
        public MainWindow( ) {
            InitializeComponent( );
        }

        private void button_Click( object sender, RoutedEventArgs e ) {
            ( Application.Current as App ).Clicked = !( Application.Current as App ).Clicked;
        }
    }
}

As a side note - I tried setting the value of the data trigger to just "True", and that also did not work ( the trigger did not catch, and text did not change based on setting the property to a new value ).

So why is the data-trigger not catching or working here? ( Either with the static resource or the literal value )? Even more relevant - why am I getting this error? The "After a 'DataTrigger' is in use (sealed), it cannot be modified" error? And what is the proper method of accomplishing what I am trying to do here? ( Preferably still using a data-trigger and not a converter, since I do need to switch between two values ).

回答1:

The local value assigned to the TextBlock's Text property has higher precedence than the value provided by the Setter in the DataTrigger. See Dependency Property Value Precedence for details.

Set the initial Text value by another Setter:

<TextBlock>
    <TextBlock.Style>
        <Style TargetType="TextBlock">
            <Setter Property="Text" Value="Unclicked"/>
            <Style.Triggers>
                <DataTrigger Binding="{Binding Clicked,
                                       Source={x:Static Application.Current}}"
                             Value="{StaticResource True}">
                    <Setter Property="Text" Value="Clicked" />
                </DataTrigger>
            </Style.Triggers>
        </Style>
    </TextBlock.Style>
</TextBlock>

The error message you see when you use the Boolean resource is just the XAML designer complaining. There is no error at runtime.