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),则背景为蓝色.因此,在重新运行窗口之前,我觉得数据触发器根本就没有运行.
在该示例中,我觉得奇怪的是您使用的是 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 属性名称中的最小错误可以解释您的行为。触发器可能基于正确的属性,但通知的名称可能拼写错误。