Why doesn't a ListBox bound to an IEnumerable update?

白昼怎懂夜的黑 提交于 2021-02-05 11:23:26

问题


I have the following 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>

and the following code for the Model class, which is put into main window's 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;
}

and main window's code:

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
    }

    private void Button_Click(object sender, RoutedEventArgs e)
    {
        var model = this.DataContext as Model;
        model.AddItem();
    }
}

When pressing the button, the contents of the list are not being updated.

However, when I change the getter of the Items property to this:

public IEnumerable<string> Items { get { return items.Values.ToList(); } }

it starts to work.

Then, when I comment out the part which sends PropertyChanged event it stops working again, which suggests that the event is being sent correctly.

So if the list receives the event, why can't it update its contents correctly in the first version, without the ToList call?


回答1:


Raising the PropertyChanged event for the Items property is only effective if the property value has actually changed. While you raise the event, the WPF binding infrastructure notices that the collection instance returned by the property getter is the same as before and does nothing do update the binding target.

However, when you return items.Values.ToList(), a new collection instance is created each time, and the binding target is updated.



来源:https://stackoverflow.com/questions/31357647/why-doesnt-a-listbox-bound-to-an-ienumerable-update

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!