[原文]
我有一个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)时,背景将变为蓝色。所以在我看来,在重新运行窗口之前,数据触发器根本就没有被运行。
答案 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的属性名称中的最小错误可以解释您的行为。触发器可以基于正确的属性,但通知可能有拼写错误的名称。