为什么ListBox没有绑定到IEnumerable更新?

时间:2015-07-11 13:26:33

标签: c# wpf data-binding

我有以下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调用的情况下,它无法在第一个版本中正确更新其内容?

1 个答案:

答案 0 :(得分:2)

提升PropertyChanged属性的Items事件仅在属性值实际更改时才有效。在引发事件时,WPF绑定基础结构会注意到属性getter返回的集合实例与以前相同,并且不会更新绑定目标。

但是,当您返回items.Values.ToList()时,每次都会创建一个新的集合实例,并更新绑定目标。