Datatrigger 适当地改变了 TextBlock 的初始属性,但不是在对象改变之后

问题描述

问题

当为我的文本块设置数据触发器时,它会毫无问题地接受认值并适当地更改前景,但是当值更改时,它不会像预期的那样更改颜色。我查看了一些答案,我应该能够以某种方式引用相对来源,但它并没有改变结果。

XAML 测试代码

            <ListBox Name="test" Width="90" Margin="20,20,40" MouseDown="TextBlock_MouseDownTest"
                 ScrollViewer.VerticalScrollBarVisibility="disabled">
            <ListBox.ItemTemplate>
                <DataTemplate>
                    <TextBlock Name="dttBlock" Text="{Binding Time}" MouseDown="TextBlock_MouseDownTest">
                        <TextBlock.Style>
                            <Style targettype="TextBlock">
                                <Style.Triggers>
                                    <DataTrigger Binding="{Binding Path =Flex}" Value="normal">
                                        <Setter Property="Foreground" Value="Blue" />
                                    </DataTrigger>
                                </Style.Triggers>
                            </Style>
                        </TextBlock.Style>
                    </TextBlock>
                </DataTemplate>
            </ListBox.ItemTemplate>
        </ListBox>

MouseDownClickEvent

        private void TextBlock_MouseDownTest(object sender,MouseButtonEventArgs e)
    {
        TimeLord item = (TimeLord) (sender as TextBlock).DataContext;
        var textBlock = sender as TextBlock;

        switch (item.Flex)
        {
            case "off":
                MessageBox.Show("normal ON");
                item.Flex = "normal";
                break;
            case "normal":
                MessageBox.Show("Flex ON");
                item.Flex = "flex";
                break;
            case "flex":
                MessageBox.Show("OFF");
                item.Flex = "off";
                break;
        }
    }

之前的实施和预期结果

如果回复的人不介意,我想就此展开更广泛的讨论。我使用数据触发器的原因是我在实现将所有列表框项目前景重置为认颜色(黑色)的按钮时遇到问题。

当前 XAML 代码

            <ListBox Name="friday" Width="90" Margin="20,40" MouseDown="TextBlock_MouseDown"
                 ScrollViewer.VerticalScrollBarVisibility="disabled" IsSynchronizedWithCurrentItem="True">
            <ListBox.ItemTemplate>
                <DataTemplate>
                    <TextBlock Text="{Binding Time}" MouseDown="TextBlock_MouseDown" />
                </DataTemplate>
            </ListBox.ItemTemplate>
        </ListBox>

当前的 C# ButtonClickEvent 代码

        private void clear_Click(object sender,RoutedEventArgs e)
    {
        List<System.Windows.Controls.ListBox> weekdays = new List<System.Windows.Controls.ListBox>
            {monday,tuesday,wednesday,jueves,friday};

        for (var i = 0; i < weekdays.Count; i++)
        {
            foreach (TimeLord item in weekdays[i].Items)
            {
                item.Flex = "off";
            }
        }
    }

更改与 listBoxitem 关联的对象没有问题,但我无法从按钮本身更改前景。我可以通过使用传递给事件的发件人为单击列表框项创建一个事件来成功更改前景。如果有一种方法可以从 ButtonClick 事件访问文本框,那可能是 Datatrigger 的替代解决方案。

This is a small clip 展示旧的实现并且我目前可以更改项目的值。

解决方法

在我的 TimeLord 类中,我从未实现过 INotifyPropertyChanged,在使用 DataTriggers 之后,一切都按照我的预期工作。

时间领主.cs

public class TimeLord : INotifyPropertyChanged {
protected void OnPropertyChanged(PropertyChangedEventArgs e)
{
    PropertyChangedEventHandler handler = PropertyChanged;
    if (handler != null)
        handler(this,e);
}

public string flex;
public string Flex
{
    get { return flex;}
    set
    {
        flex = value;
        OnPropertyChanged();
    }
}

public string Time
{
    get;
    set;
}

public event PropertyChangedEventHandler PropertyChanged;

[NotifyPropertyChangedInvocator]
public void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
    if (PropertyChanged != null)
    {
        PropertyChanged(this,new PropertyChangedEventArgs(propertyName));
    }
}

}

XAML 代码块(与之前相同,只是为了显示不止一种触发器类型)

<DataTemplate>
                    <TextBlock Name="dttBlock" Text="{Binding Time}" MouseDown="TextBlock_MouseDownTest">
                        <TextBlock.Style>
                            <Style TargetType="TextBlock">
                                <Style.Triggers>
                                    <DataTrigger Binding="{Binding Path =Flex}" Value="normal">
                                        <Setter Property="Foreground" Value="Blue" />
                                    </DataTrigger>
                                    <DataTrigger Binding="{Binding Path =Flex}" Value="flex">
                                        <Setter Property="Foreground" Value="Red" />
                                    </DataTrigger>
                                </Style.Triggers>
                            </Style>
                        </TextBlock.Style>
                    </TextBlock>
                </DataTemplate>