ItemsSource 绑定不更新值

ItemsSource binding do not update values

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

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

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

提前感谢您提供任何有用的建议。

列表框:

<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"/>

代码隐藏:

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

DataViewModel 类:

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));
        }
    }
    .
    .
    .

}

要将对集合的更改传播到 UI,集合 class 需要实施 INotifyCollectionChanged

已经实现的一个非常有用的class是ObservableCollection<T>MSDN)。使用它代替 Collection<T>.

如果 Collection 实现了 INotifyCollectionChanged 接口,则使用 ObservableColLection 代替:

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

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

相反,您可以使用 ObservableCollection<T> class (or, more precisely, any collection that also implements INotifyCollectionChanged),更改将自动传播到列表框。

请注意,您的 属性 没有 可以键入 ObservableCollection<T>,您也可以只声明 public 属性 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>,如果你想禁止来自外部的更改。

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