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

时间:2010-03-12 12:03:51

标签: wpf datatemplate datatrigger

[原文]
我有一个ListBox,其ItemsSource(在创建窗口时在后面的代码中完成)数据绑定到ObservableCollection。然后,ListBox会针对这些项目分配以下DataTemplate

usercontrol.xaml

<ListBox x:Name="communicatorListPhoneControls"
         ItemContainerStyle="{StaticResource templateForCalls}"/>

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>

使用对象更新ObservableCollection时,ListBox会显示正确的初始DataTemplate,但hasBeenAnswered属性设置为{{1 (调试时我可以看到集合是正确的)true没有重新评估,然后更新DataTrigger以使用正确的ListBox

我在我的对象中实现了DataTemplate事件,如果在模板中绑定了一个值,我可以看到值更新。只是INotifyPropertyChanged不会重新评估并更改为正确的模板。

我知道DataTrigger绑定是正确的,因为如果我关闭窗口并再次打开它,它将正确应用第二个数据模板,因为DataTrigger设置为hasBeenAnswered。< / p>

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

usercontrol.xaml

true

app.xaml:

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

现在发生的情况类似于第一个例子,当一个呼叫进入“未应答”标签显示时(每个呼叫存在一个,因为这是一个列表框 - 通常当窗口加载时将没有呼叫),然后回答呼叫并将预言<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> 设置为真,但“未回复”保持不变。如果我关闭窗口,然后再次重新打开它(当活动调用仍然将属性hasBeenAnswered设置为true)时,背景将变为蓝色。所以在我看来,在重新运行窗口之前,数据触发器根本就没有被运行。

1 个答案:

答案 0 :(得分: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>

在代码隐藏中:

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;
}

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

相关问题