个人博客同步csdn
当写WPF的时候,有时候需要对集合元素的加入、删除同步到UI上,这时使用的是ObservableCollection<T>
,但是它不能对元素内部字段进行监听并映射到UI上,所以基于它重写了一部分逻辑以实现对属性字段的监听修改,与优先队列的效果差不多了
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Linq;
namespace ClipboardShare.DS;
/// <summary>
/// 支持监听属性更改的可观察集合
/// </summary>
/// <typeparam name="T">类型</typeparam>
public class ObservablePriorityCollection<T> : ObservableCollection<T>
{
private readonly Func<T, IComparable> _prioritySelector;
public ObservablePriorityCollection(Func<T, IComparable> prioritySelector)
{
this._prioritySelector = prioritySelector ?? throw new ArgumentNullException(nameof(prioritySelector));
}
protected override void InsertItem(int index, T item)
{
if (item == null)
throw new ArgumentNullException(nameof(item));
base.InsertItem(index, item);
AddEvent(item);
Sort();
}
protected override void RemoveItem(int index)
{
base.RemoveItem(index);
Sort();
}
protected override void SetItem(int index, T item)
{
if (item == null)
throw new ArgumentNullException(nameof(item));
base.SetItem(index, item);
AddEvent(item);
Sort();
}
private void HandleItemPropertyChanged(object? sender, PropertyChangedEventArgs e)
{
Sort();
}
//添加属性变更事件
private void AddEvent(T item)
{
if (item is INotifyPropertyChanged newNotifyPropertyChanged)
{
newNotifyPropertyChanged.PropertyChanged += HandleItemPropertyChanged;
}
else
{
throw new NotSupportedException("must be implement INotifyPropertyChanged");
}
}
private void Sort()
{
var sortedItems = Items.OrderBy(_prioritySelector).ToList();
for (var i = 0; i < sortedItems.Count; i++)
{
Move(IndexOf(sortedItems[i]), i);
}
}
}
对想要监听的实体类实现 IComparable
接口以及INotifyPropertyChanged
接口 ,然后创建ObservablePriorityCollection
的时候传入就行,例如这样:
var res = new ObservablePriorityCollection<ClipBoardData>(x => x);