WPF通知链实现

时间:2013-05-23 07:34:52

标签: wpf mvvm binding notify

以下是模型:

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>

问:当响应集合发生更改时(如添加了新响应),如何通知 CustomersViewModel ,以便 CustomersView.xaml 更新它是指定客户的UI吗?

2 个答案:

答案 0 :(得分:0)

我现在实现的解决方案是一个包含CustomerRegister的类List<Customer>,并提供了获取/添加/编辑/保存a.s.o Customer对象的方法。 CustomersViewModel cantains CustomersRegister。 此外,CustomerRegister会在上升的事件处理程序发生任何更改时通知CustomersViewModel。 最后,“模型”中的每个object都会在其属性发生变化时通知CustomerRegister。 这似乎很复杂,所以我会欣赏任何其他选择。

答案 1 :(得分:0)

好的,这是我用来收听子集合变化的类。也许你可以使用它。

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