2013-05-23 1 views
1

Вот модель: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 обновит свой пользовательский интерфейс для указанного клиента?

+0

Можете ли вы опубликовать CustomerViewModel? Немного больше информации облегчает помощь. – Marc

+0

Что именно вы пытаетесь достичь? Если дизайн представлений хорош, вам не нужно уведомлять «CustomerView», потому что у вас есть что-то (например, «ResponsesList'), которое визуализирует коллекцию ответов. В этом случае у вас будет элемент 'DataTemplate', который будет обновляться автоматически. – DHN

+0

1. У меня есть «CustomerView.xaml» с «DataContext = CustomersViewModel». 2. 'CustomersView.xaml' имеет' DataGrid' с 'ItemsSource = Customers'. 3. Столбец «DataGrid» «Имя клиента» связан как «Binding = {Binding Path = Name}» 4. «DataGrid.RowDetails' имеет« DataGrid », который привязан к« Запросам »и« Ответы ». 5. Когда приложение запускается, все работает нормально, все данные отображаются так, как должно быть. 6. Когда я программно добавляю новый 'Response', данные в' DataGrid' не обновляются. Мне нужно, чтобы пользовательский интерфейс обновлялся onfly при изменении данных. –

ответ

0

Решение, которое я реализовал к настоящему времени, представляет собой класс CustomerRegister, который содержит List<Customer> и предоставляет методы получения/добавления/редактирования/сохранения объектов a.s.o Customer. CustomersViewModel cantains CustomersRegister. Кроме того, CustomerRegister уведомляет CustomersViewModel о любых изменениях, внесенных обработчиками восходящих событий. И, наконец, каждый object из «Модели» уведомляет CustomerRegister, когда его свойства изменились. Это кажется довольно сложным, поэтому я буду признателен за любой другой вариант.

+0

Можете ли вы разместить код, пожалуйста? Мне просто интересно, как вы решили, так как я сам разработал подход. : o) – DHN

+0

@DHN, я использую стандартные методы EventHandlers и Update() в ClientRegister для обновления ViewModel. Я не уверен, что ты его примешь. Он работает правильно, но обновление пользовательского интерфейса CustomerView занимает почти 10 секунд. Я буду продолжать искать ... –

+0

Я отправил вам свой класс. Не уверен, что это вам поможет. – DHN

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); 
} 
Смежные вопросы