[英]Generic-inherited classes storing their parent ObservableCollection
我有幾個 collections,每個特定的 class。我需要每個實例(模型)存儲其父集合(以便能夠通過數據驗證訪問其他實例)。 試圖找到一些聰明的解決方案 - 開始懷疑是否有這樣的。
到目前為止,我想到了以下內容。
通用基類:
public class ModelBase<T> : ObservableObject, IDataErrorInfo
{
public CustomObservableCollection<T> ParentCollection;
public int Id { get; set; } // some generic prop
}
個別類(模型):
public class Model1: ModelBase<Model1>
{
public string Name { get; set; } // Some specific prop
// Data Error validation here, e.g. check of uniqueness
if (ParentCollection?.Where(c => c.Id != Id).Any(c => c.Name == Name) == true)
{
}
}
public class Model2: ModelBase<Model2>
{}
自定義 ObservableCollection:
public class CustomObservableCollection<T> : ObservableCollection<T> where T : ModelBase<T>
{
public CustomObservableCollection() : base() { }
public CustomObservableCollection(List<T> list)
: base(list)
{
foreach (T item in list)
{
item.ParentCollection = this;
}
}
public void AddEdit(T item)
{
item.ParentCollection = this;
base.Add(item);
}
protected override void InsertItem(int index, T item)
{
base.InsertItem(index, item);
item.ParentCollection = this;
// Initialize values
}
// Generic method - I would like to call this directly from command handler regardless of type T
public void MoveItemUp(object parameter)
{
}
}
用法:
CustomObservableCollection<Model1> Model1Collection = new (listOfModel1instances);
我也一直在嘗試使用接口,但沒有成功。
由於集合中的每個項目都需要知道其父集合,因此解決此目標的一種方法是定義一個類似ISourceAware
的接口,並通過在其聲明中添加where T: ISourceAware
來約束CustomObservableCollection<T>
僅接受實現它的項目.
public interface ISourceAware
{
ICollection Source { get; set; }
}
public class CustomObservableCollection<T> : ObservableCollection<T> where T: ISourceAware
{
protected override void OnCollectionChanged(NotifyCollectionChangedEventArgs e)
{
base.OnCollectionChanged(e);
if(e.Action.Equals(NotifyCollectionChangedAction.Add))
{
foreach (ISourceAware iitem in e.NewItems)
{
iitem.Source = this;
#if DEBUG
var item = (Item)iitem;
// Try a loopback test
Console.WriteLine(
$"Index of {item.Description} is {item.ParentCollection.IndexOf(item)}");
#endif
}
}
}
}
集合處理自己的CollectionChanged
通知,將自己設置為添加到其中的任何項目的Source
。 這解決了存儲其父 ObservableCollection的主要問題——您可以使用它進行驗證,但您認為合適。
實現ISourceAware
的 class 的最小示例:
public class Item : ISourceAware
{
public string Description { get; set; } = string.Empty;
public ICollection Source { get; set; }
public CustomObservableCollection<Item> ParentCollection =>
(CustomObservableCollection<Item>)Source;
}
測試
這是我為測試此答案而編寫的快速控制台代碼。
internal class Program
{
static void Main(string[] args)
{
Console.Title = "Test ISourceAware";
var collection = new CustomObservableCollection<Item>();
collection.Add(new Item { Description = "Item 1" });
collection.Add(new Item { Description = "Item 2" });
Console.ReadKey();
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.