WPF / MVVM: делегирование коллекции модели домена в ViewModel - PullRequest
1 голос
/ 25 мая 2010

Коллекция модели домена (обычно List или IEnumerable) делегирована для ViewModel.

Это означает, что мой CustomerViewModel имеет коллекцию заказов типа List или IEnumerable.

Никакие изменения в списке не распознаются связанным элементом управления. Но с ObservableCollection это так.

Это проблема в шаблоне проектирования MVVM.

Как вы справляетесь с этим?

ОБНОВЛЕНИЕ : пример того, как я это делаю:

 public class SchoolclassViewModel : ViewModelBase
{
    private Schoolclass _schoolclass;
    private ObservableCollection<PupilViewModel> _pupils = new ObservableCollection<PupilViewModel>();        

    public SchoolclassViewModel(Schoolclass schoolclass)
    {
        _schoolclass = schoolclass;
        _schoolclass.Pupils = new List<Pupil>();

        foreach (var p in schoolclass.Pupils)           
            Pupils.Add(new PupilViewModel(p));            
    }

    public Schoolclass GetSchoolclass 
    {
        get { return _schoolclass; } 
    }

    public int ID { get; set; }       

    public string SchoolclassName
    {
        get { return _schoolclass.SchoolclassName;}
        set
        { 
            if(_schoolclass.SchoolclassName != value)
            {                    
                _schoolclass.SchoolclassName = value;
                this.RaisePropertyChanged("SchoolclassName");
            }

        }
    }   

    public ObservableCollection<PupilViewModel> Pupils
    {
        get{ return _pupils;}
        set
        {
            _pupils = value;
            this.RaisePropertyChanged("Pupils");
        } 
    }
}

Ответы [ 3 ]

3 голосов
/ 25 мая 2010

Я имею дело с этим, не поступая так, как вы описываете.

Если мне нужно представить объект Foo и связанные с ним объекты Bar в представлении, FooViewModel обычно реализует свойство Bars типа ObservableCollection<BarViewModel>.

Обратите внимание, что это независимо от того, имеет ли базовый класс Foo свойство Bars типа IEnumerable<Bar>. Класс Foo может и не быть. Приложению может даже не потребоваться иметь возможность перебирать все объекты Bar для Foo, за исключением пользовательского интерфейса.

Редактировать

Когда мое представление представляет собой простое представление объектной модели приложения, я в значительной степени поступаю так же, как вы в своем примере. Код в моем конструкторе, как правило, немного более компактен:

_Bars = new ObservableCollection<BarViewModel>(
   _Foo.Bars.Select(x => new BarViewModel(x)));

но по сути это одно и то же.

Но это предполагает, что Foo действительно выставляет свойство Bars. Возможно, нет. Или, может быть, только несколько Bar объектов должны появиться в представлении. Или, может быть, они должны выглядеть смешанными с другими объектами, а FooViewModel должен отображать CompositeCollection некоторого вида.

Я хочу сказать, что модель вида - это модель вида 1035 *. Это не обязательно имеет прямое соответствие с базовой объектной моделью.

Чтобы выбрать простой пример: моя программа может дать пользователю возможность поместить элементы в пять различных категорий, перетаскивая их в пять различных элементов управления ListBox. В конечном счете, выполнение этого устанавливает свойство Category объекта Item. Моя модель представления будет иметь коллекцию CategoryViewModel объектов, каждый со свойством типа ObservableCollection<ItemViewModel>, так что перетаскивание элементов назад и вперед между коллекциями будет простым в реализации.

Дело в том, что в объектной модели приложения может даже не быть класс a Category, не говоря уже о коллекции Category объектов. Item.Category может быть просто свойством типа string. CategoryViewModel не отражает объектную модель приложения. Он существует только для поддержки представления в пользовательском интерфейсе.

0 голосов
/ 08 июня 2010

Вместо использования ObservableCollection в моей доменной модели я использую собственный тип коллекции, который реализует интерфейс INotifyCollectionChanged среди других полезных стандартных и пользовательских интерфейсов. Мой образ мышления таков, что Rockford Lhotka в своей книге предполагает, что уведомление об изменениях полезно не только для уровня представления, поскольку другие бизнес-объекты на уровне домена часто нуждаются в некотором уведомлении при изменении состояния. в другом объекте.

С помощью этой методологии вы можете создать свой собственный тип коллекции, который по-прежнему обладает преимуществами уведомлений об изменениях, а также того, что вам когда-либо понадобится. Базовый класс для вашей коллекции может быть реализован как чисто инфраструктурный код, а затем может быть создан подкласс, который может содержать бизнес-логику, используя технику уровня подтипов, используемую в этой книге . Таким образом, в итоге вы можете получить коллекцию, которая может обернуть типы IEnumerable <> и предоставить вам информацию об изменениях, которую вы ищете, а также модель домена и код представления.

0 голосов
/ 27 мая 2010

Хорошо, я пойду дальше и добавлю свои мысли как ответ, а не в комментарии.:)

Я думаю, суть в том, что это просто реальность работы WPF и привязки данных.Для того чтобы двустороннее связывание данных работало, коллекции должны иметь средства уведомления о связанных с ними элементах управления, и стандартные списки и коллекции, используемые в большинстве объектов домена, не поддерживают / не будут / не должны поддерживать это.Как я уже упоминал в комментарии, необходимость реализации INotifyPropertyChanged для несобираемых свойств - это еще одно требование, которое не может быть выполнено стандартным объектом домена.

Объекты домена не предназначены для использования в качестве моделей представления, и для этогоПричина, по которой вы можете обнаружить, что вам нужно отображать объекты между двумя типами.Это не отличается от необходимости сопоставления между объектами домена и объектами доступа к данным.Каждый тип объекта имеет различные функции в системе, и каждый из них должен быть специально разработан для поддержки своей собственной роли в системе.

Все это говорит о том, что идея Agies использовать AOP для автоматической генерации прокси-классов очень интересна, и я собираюсь разобраться с ней.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...