我有以下XAML:
<Window x:Class="ListBoxTest.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:ListBoxTest"
Title="MainWindow" Height="350" Width="525">
<Window.DataContext>
<local:Model />
</Window.DataContext>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<ListBox ItemsSource="{Binding Items}" Grid.Row="0"/>
<Button Content="Add" Click="Button_Click" Grid.Row="1" Margin="5"/>
</Grid>
</Window>
以及Model
类的以下代码,它放在主窗口的DataContext
中:
public class Model : INotifyPropertyChanged
{
public Model()
{
items = new Dictionary<int, string>();
}
public void AddItem()
{
items.Add(items.Count, items.Count.ToString());
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs("Items"));
}
private Dictionary<int, string> items;
public IEnumerable<string> Items { get { return items.Values; } }
public event PropertyChangedEventHandler PropertyChanged;
}
和主窗口的代码:
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void Button_Click(object sender, RoutedEventArgs e)
{
var model = this.DataContext as Model;
model.AddItem();
}
}
按下按钮时,列表内容不会更新。
但是,当我将Items
属性的getter更改为:
public IEnumerable<string> Items { get { return items.Values.ToList(); } }
它开始起作用了。
然后,当我注释掉发送PropertyChanged
事件的部分时,它会再次停止工作,这表明事件正在正确发送。
因此,如果列表收到该事件,为什么在没有ToList
调用的情况下,它无法在第一个版本中正确更新其内容?
答案 0 :(得分:2)
提升PropertyChanged
属性的Items
事件仅在属性值实际更改时才有效。在引发事件时,WPF绑定基础结构会注意到属性getter返回的集合实例与以前相同,并且不会更新绑定目标。
但是,当您返回items.Values.ToList()
时,每次都会创建一个新的集合实例,并更新绑定目标。