模型:
public class Customer
{
string Name;
public ObservableCollection<Order> orders;
}
public class Order
{
int Id;
public ObservableCollection<RequestStorage> Requests;
}
public class RequestStorage
{
string Text;
public ObservableCollection<Response> Responses;
}
public class Response
{
string Text;
}
CustomersView。xaml绑定到CustomersViewModel,它有一个属性ObservableCollection<*Customer*> Customers;
CustomersViewModel
<!-- language: c# -->
public class CustomersViewModel
{
public CustomersViewModel()
{
//Load customers from database to Customers
}
public ObservableCollection<Customer> Customers { get; set; }
}
CustomersView.xaml 窗口的DataContext
设置为CustomersViewModel
<DataGrid ItemsSource="{Binding Path=Customers}">
...
<DataGridTextColumn Header="Customer name" Binding="{Binding Path=Name}" />
...
<DataGrid.RowDetailsTemplate>
<DataTemplate>
<DataGrid ItemsSource="{Binding Path=Orders}">
...
<DataGridTextColumn Binding="{Path=Id}" />
<DataGridTemplateColumn>
<ItemsControl Binding="{Path=Requests}" />
</DataGridTemplateColumn>
<DataGridTemplateColumn>
<ItemsControl DataContext="{Binding Requests}" Binding="{Path=Responses}" />
</DataGridTemplateColumn>
</DataGrid>
</DataTemplate>
</DataGrid.RowDetailsTemplate>
</DataGrid>
Q:我如何通知CustomersViewModel当响应集合发生变化时(例如添加了一个新的响应),以便CustomersView。xaml将为指定的客户更新其UI ?
我现在实现的解决方案是一个包含List<Customer>
的类CustomerRegister
,并提供获取/添加/编辑/保存a.s.o Customer
对象的方法。CustomersViewModel
包含CustomersRegister
。此外,当上升事件处理程序进行任何更改时,CustomerRegister
通知CustomersViewModel
。最后,当"模型"中的每个object
的属性发生变化时,都会通知CustomerRegister
。这似乎很复杂,如果有其他选择,我将不胜感激。
好的,这就是我用来侦听子集合变化的类。也许你可以用它。
public abstract class ChildListenerBase
{
public void RegisterChildCollection<T>(ObservableCollection<T> collection)
where T : INotifyPropertyChanged
{
// register to collection changed event
collection.CollectionChanged += OnCollectionChangedInternal;
// register to items
foreach (T item in collection)
item.PropertyChanged += OnItemPropertyChanged;
}
public void UnregisterChildCollection<T>(ObservableCollection<T> collection)
where T : INotifyPropertyChanged
{
// unregister to collection changed event
collection.CollectionChanged -= OnCollectionChangedInternal;
// unregister to item
foreach (T item in collection)
item.PropertyChanged -= OnItemPropertyChanged;
}
private void OnCollectionChangedInternal(object sender, NotifyCollectionChangedEventArgs e)
{
// probably you have to add some more cases
switch (e.Action)
{
case NotifyCollectionChangedAction.Add:
foreach (object item in e.NewItems)
((INotifyPropertyChanged) item).PropertyChanged += OnItemPropertyChanged;
break;
case NotifyCollectionChangedAction.Remove:
foreach (object item in e.OldItems)
((INotifyPropertyChanged) item).PropertyChanged -= OnItemPropertyChanged;
break;
}
OnCollectionChanged(sender, e);
}
protected virtual void OnCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
// override method in derived class to handle some additional stuff
}
// implement the reaction on item changes here
protected abstract void OnItemPropertyChanged(object sender, PropertyChangedEventArgs e);
}