属性更改后DataTrigger不会重新评估

5 wpf datatrigger datatemplate

[原创]
我有一个ListBox有它ItemsSource(这是在创建窗口后面的代码中完成)数据绑定到ObservableCollection.该ListBox则有以下DataTemplate分配对项目:

usercontrol.xaml

<ListBox x:Name="communicatorListPhoneControls"
         ItemContainerStyle="{StaticResource templateForCalls}"/>
Run Code Online (Sandbox Code Playgroud)

App.xaml中

<Style x:Key="templateForCalls" TargetType="{x:Type ListBoxItem}">  
    <Setter Property="ContentTemplate" Value="{StaticResource templateRinging}"/>  
        <Style.Triggers>  
            <DataTrigger Binding="{Binding Path=hasBeenAnswered}" Value="True">  
                <Setter Property="ContentTemplate" Value="{StaticResource templateAnswered}"/>  
            </DataTrigger>  
        </Style.Triggers>  
    </Setter>
</Style>
Run Code Online (Sandbox Code Playgroud)

ObservableCollection使用对象更新时,这将显示在ListBox正确的初始值中DataTemplate,但是当hasBeenAnswered属性设置为true(当调试时我可以看到集合是正确的)时,DataTrigger不会重新评估,然后更新ListBox以使用正确的DataTemplate.

INotifyPropertyChanged在我的对象中实现了Event,如果在模板中绑定了一个值,我可以看到值更新.它只是DataTrigger不会重新评估和更改为正确的模板.

我知道DataTrigger绑定是正确的,因为如果我关闭窗口并再次打开它,它将正确应用第二个datatemplate,因为hasBeenAnswered设置为true.

[编辑1]
根据Timores的评论,我尝试了以下内容:

usercontrol.xaml

<ListBox x:Name="communicatorListPhoneControls"
         ItemTemplate="{StaticResource communicatorCallTemplate}"/>`  
Run Code Online (Sandbox Code Playgroud)

App.xaml中:

<DataTemplate x:Key="communicatorCallTemplate">
    <Label x:Name="test">Not answered</Label>
        <DataTemplate.Triggers>
            <DataTrigger Binding="{Binding Path=hasBeenAnswered}" Value="True">
                <Setter TargetName="test" Property="Background" Value="Blue"/>
            </DataTrigger>    
        </DataTemplate.Triggers>
    </Label>
</DataTemplate>
Run Code Online (Sandbox Code Playgroud)

现在会发生什么类似于第一个例子中,当有电话打进来,在"不回答"标签显示(每存在,因为这调用一个是一个列表框-通常是当窗口负载不会有呼叫),呼叫然后回答并且预言hasBeenAnswered被设置为真,但"未回答"仍然是相同的.如果我关闭窗口,并再次重新打开它(当活动调用仍然将属性hasBeenAnswered设置为true),则背景为蓝色.因此,在重新运行窗口之前,我觉得数据触发器根本就没有运行.

Tim*_*res 1

在该示例中,我觉得奇怪的是您使用的是 ItemContainerStyle 而不是 ItemTemplate。

ItemContainerStyle 适用于包含 ItemsSource 中每个元素的 ListBoxItem。ListboxItem 没有hasBeenAnswered属性,因此我不知道绑定如何工作。

我建议为列表框中的数据类型创建一个 DataTemplate,并使用触发器进行与您的样式相同的更改templateAnswered

编辑:OP 使用 ItemTemplate 的建议后。

我尝试重现该示例,它对我来说效果很好。这是我的 XAML(请忽略样式,这只是一个示例):

无解答

    <ListBox x:Name="communicatorListPhoneControls" 
             ItemTemplate="{StaticResource communicatorCallTemplate}"/>

    <Button Margin="0,20,0,0" Click="OnToggleAnswer" Content="Toggle answer status" />
</StackPanel>
Run Code Online (Sandbox Code Playgroud)

在后面的代码中:

public partial class Window1 : Window {

    public Window1() {
        InitializeComponent();

        List<PhoneCall> lpc = new List<PhoneCall>()
        {new PhoneCall(), new PhoneCall(), new PhoneCall(), new PhoneCall()};

        communicatorListPhoneControls.ItemsSource = lpc;
    }

    private void OnToggleAnswer(object sender, RoutedEventArgs e) {

        object o = communicatorListPhoneControls.SelectedItem;

        if (o != null) {

            PhoneCall pc = (PhoneCall) o;
            pc.hasBeenAnswered = ! pc.hasBeenAnswered;
        }
    }
}

public class PhoneCall : INotifyPropertyChanged {

    private bool _answered;


    public bool hasBeenAnswered {
        get { return _answered;  }
        set {
            if (_answered != value) {
                _answered = value;
                FirePropertyChanged("hasBeenAnswered");
            }
        }
    }

    private void FirePropertyChanged(string propName) {

        if (PropertyChanged != null) {

            PropertyChanged(this, new PropertyChangedEventArgs(propName));
        }
    }
    public event PropertyChangedEventHandler PropertyChanged;
}
Run Code Online (Sandbox Code Playgroud)

你能尝试重现这个并与你的代码进行比较吗?注意:PropertyChanged 属性名称中的最小错误可以解释您的行为。触发器可能基于正确的属性,但通知的名称可能拼写错误。