gpt4 book ai didi

c# - 将事件从可观察对象引发到它的容器

转载 作者:太空宇宙 更新时间:2023-11-03 13:33:58 25 4
gpt4 key购买 nike

我有一个 MVVM 应用程序,并将数据绑定(bind)到一个可观察集合的网格。集合排序如下:

 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 ObservableCollections 项目。

我建议使用自定义集合,它实现了 INotifyCollectionChanged . ObservableCollection 不支持您要求的功能,也不是 WPF 的 CollectionViewSource这是 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>并引发与 ObservableCollection<T> 相同的事件在相应的操作上( Add(T)Remove(T)Clear() )。此外,它还执行 Sort()在添加或删除项目并订阅 INotifyPropertyChanged 时执行操作每个项目的事件在项目发生变化时执行排序。注意,集合 Reset在各种情况下都提出了。这不是一个非常高效的解决方案,但您可以根据需要通过实现自定义排序操作​​来优化它。

关于c# - 将事件从可观察对象引发到它的容器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19378854/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com