我有一個FamilyItemVM用于系結到TreeView源的類。此類用于主視圖模型。我想知道何時FamilyItemVM更改(即在 UI 中添加或洗掉子項)。
主虛擬機:
public class FamilyVM : ObservableRecipient
{
private ObservableCollection<FamilyItemVM> myFamilies;
public FamilyVM()
{
myFamilies = new ObservableCollection<FamilyItemVM>();
Families.CollectionChanged = FamilyCollectionChanged;
BuildTree();
}
public ObservableCollection<FamilyItemVM> Families // the property binded to the Treeview
{
get { return myFamilies; }
}
private void BuildTree()
{
//... the method which populate myFamilies property recursively
}
private void FamilyCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
//Here I want to know when something has changed (only add and remove items) in the whole object
}
}
物品類別:
public class FamilyItemVM : ObservableObject
{
FamilyItemVM myParent;
public FamilyItemVM(FamilyItemVM parent)
{
Items = new ObservableCollection<FamilyItemVM>();
myParent = parent;
}
public ObservableCollection<FamilyItemVM> Items { get; set; }
}
現在,當在 UI 中添加或洗掉專案時,如何在FamilyCollectionChanged方法中通知每個父級最終通知主 VM。
uj5u.com熱心網友回復:
在您當前的設計中,每個FamilyItemVM都只知道它的 parent FamilyItemVM。因此,需要向上通知您的家庭專案樹的更改。這可以通過每當Items集合更改時引發的事件來完成。事實上,這正是 anObservableCollection對其CollectionChanged事件所做的事情。您也可以重用相同的引數型別,即NotifyCollectionChangedEventArgs. 不同之處在于我們需要將事件一直傳播到根專案。
下面的方法公開了一個事件DescendantsChanged,它通知Items層次結構中任何位置的任何集合都發生了變化。每個都通過處理事件來FamilyItemVM偵聽自己的Items集合更改。CollectionChanged如果添加了任何事件,則會添加FamilyItemVM其自身DescendantsChanged事件的處理程式。此處理程式只是對任何后代更改做出反應并引發DescendantsChanged其自己的實體(當前的父級FamilyItemVM)以通知其自己的父級。
讓我們使用這種機制回顧一下此時發生的情況:
- Any
FamilyItemVM觀察它的Items集合。 - 添加了一個觸發
CollectionChanged事件的專案。 - 事件的處理程式
DescendantsChanged被添加到專案中。 DescendantsChanged當前實體(新專案的父項)上的事件this被引發。- 偵聽事件的父
DescendantsChanged級(在 2. 中添加)呼叫其處理程式,對其作出反應并引發其DescendantsChanged事件以通知其父級的相同方式(參見 4.)。 - 一直這樣,直到不再有父級,
_myParent是null。
最后一點null是您提供的代碼的假設,我稍后會解釋。
public class FamilyItemVM : ObservableObject
{
private readonly FamilyItemVM _myParent;
public FamilyItemVM(FamilyItemVM parent)
{
_myParent = parent;
Items = new ObservableCollection<FamilyItemVM>();
Items.CollectionChanged = OnItemsChanged;
// If the Items collection can be reassigned (has a setter), remove this and the child handlers again.
// Otherwise there may be a memory leak. This must be triggered from the setter.
}
public ObservableCollection<FamilyItemVM> Items { get; set; }
// An event to notify that ANY of the descendent Items collections changed.
public event NotifyCollectionChangedEventHandler DescendantsChanged;
private void OnItemsChanged(object sender, NotifyCollectionChangedEventArgs e)
{
// Add the handler to any new VM that is added.
if (e.Action == NotifyCollectionChangedAction.Add)
{
foreach (var newItem in e.NewItems)
{
var descendantFamilyItemVm = (FamilyItemVM)newItem;
descendantFamilyItemVm.DescendantsChanged = OnDescendantsChanged;
}
}
// Remove the handler if a child is removed to prevent a memory leak.
if (e.Action == NotifyCollectionChangedAction.Remove)
{
foreach (var oldItem in e.OldItems)
{
var descendantFamilyItemVm = (FamilyItemVM)oldItem;
descendantFamilyItemVm.DescendantsChanged -= OnDescendantsChanged;
}
}
// You should handle other collection changed actions, too, e.g. Reset.
// ...
// React to changes of this Items collection.
// ...
// Notify that descendants have changed.
DescendantsChanged?.Invoke(this, e);
}
private void OnDescendantsChanged(object sender, NotifyCollectionChangedEventArgs e)
{
// React to any of the descendants having their Items collection changed.
// ...
var familyItemVm = (FamilyItemVM)sender;
// Notify parent that any of its descendants changed its Items collection.
// The sender here is the descendant that originally raised the event.
DescendantsChanged?.Invoke(sender, e);
}
}
現在,根據您的代碼,我假設添加到myFamilies中的最頂層專案FamilyVM已null像parent在建構式中一樣通過,因為您無法通過FamilyVM. 這意味著,FamilyVM沒有通知。
要解決此問題,您只需FamilyCollectionChanged在. 但請注意,您必須在添加更多子項之前將處理程式添加到根項,否則此時您不會收到通知。DescendantsChangedFamilyVM
private void BuildTree()
{
// ...code to build the root items.
foreach (var familyItemVm in myFamilies)
familyItemVm.DescendantsChanged = FamilyCollectionChanged;
// ...even more code to add the the children.
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/516408.html
下一篇:影像未顯示在WPF的切換按鈕中
