为什么ListBox绑定到IEnumerable更新?
我有以下XAML:为什么ListBox绑定到IEnumerable更新?
<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
?
提高Items
属性的PropertyChanged
事件仅在属性值实际发生更改时才有效。在引发事件时,WPF绑定基础结构注意到属性getter返回的集合实例与之前相同,并且不会更新绑定目标。
但是,当您返回items.Values.ToList()
时,每次都创建一个新的集合实例,并更新绑定目标。
似乎我完全误解了'PropertyChanged'是什么:)这完全有道理,在我正在阅读有关该主题的内容中。谢谢! – BartoszKP
我不知道它是否正好相关,但有时会调用'NotifyPropertyChanged(null)'(使用null作为参数而不是属性名称),屏幕上的_every_属性会更新。它为我过去解决了一些问题。 – heltonbiker
@heltonbiker即使您通知所有属性(而不是特定属性)的更改,也不会更新绑定目标,因为源集合实际上并未发生更改。 – Clemens
你有没有考虑过使用ObservableCollection? – heltonbiker
@heltonbiker它有严重的缺点 - 像缺少“AddRange”,也没有其他可能性执行批量更新,这不会导致每个添加项目的更新。另外,我有一本字典不是一个普通的列表。 – BartoszKP
@BartoszKP有可用的可观察字典的实现(只需搜索ObservableDictionary)。您可以将ListBox的ItemsSource直接绑定到ObservableDictionary,并将ListBox项目(在ItemTemplate中)绑定到字典条目的'Value'属性。 – Clemens