wpf ItemsSource 绑定不更新值

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/27747357/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-13 12:49:21  来源:igfitidea点击:

ItemsSource binding do not update values

c#wpfxaml

提问by Qerts

I need to make list of items. I binded collection of users to listbox. Everything works quite well, but items in listbox aren't updated in real time. They aren't updated at all by this binding. So when I remove any user from the list, listbox isn't updated even if its source is correctly changed.

我需要列出物品清单。我将用户集合绑定到列表框。一切正常,但列表框中的项目不会实时更新。此绑定根本不会更新它们。因此,当我从列表中删除任何用户时,即使正确更改了其来源,列表框也不会更新。

Source is located in data view model at path DataViewModel.Instance.AllUsers; Whenever I add to this list new item or remove one, layout does not update. Other bindings work well. I tried to update listbox layout, to raise event of source update, other way of adding/removing items, but nothing worked.

源位于路径 DataViewModel.Instance.AllUsers 处的数据视图模型中;每当我向此列表添加新项目或删除一个项目时,布局都不会更新。其他绑定效果很好。我试图更新列表框布局,引发源更新事件,添加/删除项目的其他方式,但没有任何效果。

I tried to debug binding, but I have too many bindings to find the error.

我试图调试绑定,但我有太多的绑定无法找到错误。

Thanks in advance for any useful advice.

在此先感谢您提供任何有用的建议。

Listbox:

列表框:

<ListBox x:Name="ListboxUsers" ItemsSource="{Binding Path=AllUsers, Mode=OneWay}" Grid.Column="1" Margin="0" Grid.Row="5" Background="DimGray" BorderThickness="0" Visibility="Hidden" SelectionChanged="ListboxUsers_SelectionChanged"/>

Code-behind:

代码隐藏:

CatalogueGrid.DataContext = DataViewModel.Instance;    //whole view model added as datacontext

DataViewModel class:

数据视图模型类:

public class DataViewModel : INotifyPropertyChanged
{
    private static DataViewModel _dataViewModel;

    private Collection<UserModel> allUsers;
    public Collection<UserModel> AllUsers
    {
        get
        {
            return allUsers;
        }
        set
        {
            allUsers = value;
            NotifyPropertyChanged("AllUsers");
        }
    }


    private DataViewModel()
    {
        AllUsers = new Collection<UserModel>();
    }    

    public event PropertyChangedEventHandler PropertyChanged;
    private void NotifyPropertyChanged(string info)
    {
        PropertyChangedEventHandler handler = PropertyChanged;
        if (handler != null)
        {
            handler(this, new PropertyChangedEventArgs(info));
        }
    }
    .
    .
    .

}

回答by ELH

use ObservableColLectioninstead if Collectionwich implements the INotifyCollectionChangedInterface :

ObservableColLection,而是如果Collection至极实现了INotifyCollectionChanged接口:

private ObservableCollection<UserModel> allUsers;
public ObservableCollection<UserModel> AllUsers
{
    get
    {
        return allUsers;
    }
    set
    {
        allUsers = value;
        NotifyPropertyChanged("AllUsers");
    }
}

回答by BradleyDotNET

For changes to the collection to propagate to the UI, the collection class needs to implement INotifyCollectionChanged.

为了将集合的更改传播到 UI,集合类需要实现INotifyCollectionChanged.

A very useful class that alreadyimplements this is ObservableCollection<T>(MSDN). Use that instead of Collection<T>.

已经实现了这一点的一个非常有用的类是ObservableCollection<T>( MSDN)。使用它而不是Collection<T>.

回答by O. R. Mapper

You have bound your listbox to a Collection<T>- that is just a list, which does not issue any notifications to bound properties that its contents has changed. Hence, your listbox cannot possibly know when the collection has changed.

您已将列表框绑定到 a Collection<T>- 这只是一个列表,它不会向绑定的属性发出任何通知,说明其内容已更改。因此,您的列表框不可能知道集合何时发生变化。

Instead, you can use the ObservableCollection<T>class(or, more precisely, any collection that also implements INotifyCollectionChanged), and changes will be automatically propagated to the listbox.

相反,您可以使用ObservableCollection<T>该类(或者更准确地说,任何也实现 的集合INotifyCollectionChanged),并且更改将自动传播到列表框。

Note that your property does not haveto be typed as ObservableCollection<T>, you can also just declare your public property as IEnumerable<T>or IList<T>; the binding will find out on its own whether the returned class also implements INotifyCollectionChanged. Like this, you are free to replace your actual underlying collection class later on, for example with a ReadOnlyObservableCollection<T>, in case you want to disallow changes from the outside.

请注意,你的财产不具有被分类为ObservableCollection<T>,你也可以只申报您的公共财产IEnumerable<T>IList<T>; 绑定将自行确定返回的类是否也实现INotifyCollectionChanged. 像这样,您以后可以自由地替换实际的底层集合类,例如ReadOnlyObservableCollection<T>,如果您想禁止来自外部的更改,则可以使用 a 替换。

Speaking of this, a note on your code: You have provided your AllUsersproperty with a setter. This may lead to undesired consequences, as you open up possibilities for some other code to set the property to null, which (depending on the rest of your code) might lead to exceptions. Unless you actually want to allow assigning new values, for the ItemsSourceproperty binding, a read-only property is fully sufficient, as long as the returned collection object implements INotifyCollectionChanged.

说到这里,请注意您的代码:您已经为您的AllUsers财产提供了一个 setter。这可能会导致意外后果,因为您为其他一些代码打开了将属性设置为 的可能性null,这(取决于您的代码的其余部分)可能会导致异常。除非您确实希望允许分配新值,否则对于ItemsSource属性绑定,只读属性就完全足够了,只要返回的集合对象实现INotifyCollectionChanged.