WPF通知链实现



模型:

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);
}

最新更新