代码之家  ›  专栏  ›  技术社区  ›  snemarch

WPF:在不清除/添加的情况下替换数据绑定集合内容

  •  8
  • snemarch  · 技术社区  · 14 年前

    当使用WPF数据绑定时,我显然不能按照 MyCollection = new CollectionType<Whatever>( WhateverQuery() ); 因为绑定具有对旧集合的引用。到目前为止我的工作范围是 MyCollection.Clear(); 接着做前臂动作 MyCollection.Add(item); -这对表演和美学都很不利。

    ICollectionView 虽然很整洁,但也不能解决问题,因为 SourceCollection 属性是只读的;很糟糕,因为这是一个很好且简单的解决方案。

    其他人是如何处理这个问题的?应该提到,我正在执行MVVM,因此无法通过单个控件绑定进行搜索。我想我可以做个包装纸 ObservableCollection 体育运动 ReplaceSourceCollection() 方法,但在走这条路之前,我想知道是否还有其他的最佳实践。

    编辑:

    对于WinForms,我将针对 BindingSource ,允许我简单地更新 DataSource 属性并调用 ResetBindings() 方法-Presto,基础集合已有效更改。我希望WPF数据绑定能够支持开箱即用的类似场景?

    示例(伪ish)代码:wpf控件(listbox、datagrid,随便您喜欢什么)绑定到 Users 财产。我认识到集合应该是只读的,以避免 ReloadUsersBad() ,但是这个示例的错误代码显然不会编译:)

    public class UserEditorViewModel
    {
        public ObservableCollection<UserViewModel> Users { get; set; }
    
        public IEnumerable<UserViewModel> LoadUsersFromWhateverSource() { /* ... */ }
    
        public void ReloadUsersBad()
        {
            // bad: the collection is updated, but the WPF control is bound to the old reference.
            Users = new ObservableCollection<User>( LoadUsersFromWhateverSource() );
        }
    
        public void ReloadUsersWorksButIsInefficient()
        {
            // works: collection object is kept, and items are replaced; inefficient, though.
            Users.Clear();
            foreach(var user in LoadUsersFromWhateverSource())
                Users.Add(user);
        }
    
        // ...whatever other stuff.
    }
    
    2 回复  |  直到 14 年前
        1
  •  4
  •   Pieter van Ginkel    14 年前

    MyCollection INotifyPropertyChanged

    public class MyClass : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;
        private ObservableCollection<Whatever> _myCollection;
    
        private void NotifyChanged(string property)
        {
            if (PropertyChanged != null)
                PropertyChanged(this, new PropertyChangedEventArgs(property));
        }
    
        public ObservableCollection<Whatever> MyCollection
        {
            get
            {
                return _myCollection;
            }
            set
            {
                if (!ReferenceEquals(_myCollection, value))
                {
                    _myCollection = value;
                    NotifyChanged("MyCollection");
                }
            }
        }
    }