将事件从可观察对象引发到其容器
本文关键字:对象 事件 观察 | 更新日期: 2023-09-27 18:35:37
我有一个MVVM应用程序,并将数据绑定到可观察集合的网格。 集合的排序如下:
public ObservableCollection<MyObject> MyData
{
get
{
return _myData;
}
set
{
_myData = new ObservableCollection<MyObject>(value.OrderByDescending(s => s.DateParam));
RaisePropertyChanged(() => MyData);
}
}
当我添加一个条目时,这工作正常,但是,MyObject.DateParam
日期可能会更改。 尽管对象和集合都引发了NotifyPropertyChanged
,如图所示,但它不会更新。 我的解决方法如下:
SelectedDataEntry.DateParam = DateTime.Now;
MyData = MyData;
请有人告诉我有一种更光滑的方法可以做到这一点。
你的问题不是关于引发ObservableCollection
的更改事件,而只是关于如何提供一个有序的可观察集合,它响应INotifyPropertyChanged
的可观察集合项。
我建议使用自定义集合,它实现了INotifyCollectionChanged
。ObservableCollection
和 WPF 的 CollectionViewSource
都不支持您要求的功能,WPF 是 WPF 用于排序和筛选集合的内部解决方案。
这是我的实现,我还没有测试过它,但你应该让它按预期工作:
/// <summary>
/// ObservableCollection, supporting sorting of items
/// which automatically refreshes when items notify property changes.
/// </summary>
/// <typeparam name="T">Item type</typeparam>
public sealed class SortableObservableCollection<T> : INotifyCollectionChanged, ICollection<T>
{
private readonly IComparer<T> _comparer;
private readonly List<T> _innerItems;
public SortableObservableCollection(IComparer<T> comparer)
{
_comparer = comparer;
_innerItems = new List<T>();
}
public SortableObservableCollection(IEnumerable<T> collection, IComparer<T> comparer)
{
_comparer = comparer;
_innerItems = new List<T>(collection);
}
private void Item_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
Sort();
}
public void Sort()
{
_innerItems.Sort(_comparer);
}
public event NotifyCollectionChangedEventHandler CollectionChanged;
private void RaiseAdd(T newItem)
{
if (CollectionChanged != null) CollectionChanged(this, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, newItem));
}
private void RaiseRemoved(T oldItem)
{
if (CollectionChanged != null) CollectionChanged(this, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Remove, oldItem));
}
private void RaiseReset()
{
if (CollectionChanged != null) CollectionChanged(this, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
}
public IEnumerator<T> GetEnumerator()
{
return _innerItems.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
public void Add(T item)
{
// Subscribe to items change notification
var inpc = item as INotifyPropertyChanged;
if (inpc != null) inpc.PropertyChanged += Item_PropertyChanged;
_innerItems.Add(item);
Sort();
RaiseAdd(item);
RaiseReset();
}
public void Clear()
{
foreach (var innerItem in _innerItems)
{
var inpc = innerItem as INotifyPropertyChanged;
if (inpc != null) inpc.PropertyChanged -= Item_PropertyChanged;
}
_innerItems.Clear();
RaiseReset();
}
public bool Contains(T item)
{
return _innerItems.Contains(item);
}
public void CopyTo(T[] array, int arrayIndex)
{
_innerItems.CopyTo(array, arrayIndex);
}
public bool Remove(T item)
{
// Unsubscribe from item's change notification
var inpc = item as INotifyPropertyChanged;
if (inpc != null) inpc.PropertyChanged -= Item_PropertyChanged;
var removed = _innerItems.Remove(item);
if (!removed) return false;
Sort();
RaiseRemoved(item);
RaiseReset();
return true;
}
public int Count { get { return _innerItems.Count; }}
public bool IsReadOnly { get { return false; } }
}
它基本上包装了一个List<T>
,并在相应的操作(Add(T)
、Remove(T)
、Clear()
)上引发与ObservableCollection<T>
相同的事件。此外,它在添加或删除项目时执行Sort()
操作,并订阅每个项目的 INotifyPropertyChanged
事件,以便在项目发生更改时执行排序。请注意,集合Reset
在每种排序上都会引发。这不是一个性能很高的解决方案,但您可以通过实现自定义排序操作来根据需要对其进行优化。
为什么不创建可观察的集合,例如:
private ObservableCollection<MyObject> _myData = new ObservableCollection<MyObject>();
public ObservableCollection<MyObject> MyData
{
get{ return _myData;}
}
然后例如
MyData[0].DateParam = DateTime.Now;
MyData.OrderByDescending(s => s.DateParam);