Заголовок Silverlight MVVM подробно - PullRequest
2 голосов
/ 13 марта 2009

Допустим, у меня есть OrderModel и OrderViewModel. У меня есть свойства «Поставщик», «Дата заказа» и т. Д. Как в ViewModel, так и в модели, и они связаны между собой. Видел примеры по этому поводу и кажется достаточно простым, хотя и несколько дублированным с точки зрения написания сеттеров / геттеров.

Что мне теперь делать с OrderDetails? В моей модели у меня был бы список.

Есть ли у меня OrderDetailViewModel для OrderDetail? Если так, то как это обеспечивает OrderViewModel? Как ObservableCollection? И если да, то как вы поддерживаете это в синхронизации с первоначальным списком?

Здесь я не видел достойного примера. Если есть кто-то, на кого можно было бы указать мне, я был бы признателен. Мне нравится концепция MVVM, но я начинаю думать, что это чертовски много накладных расходов. Почему бы просто не сделать так, чтобы ViewModel обрабатывал часть модели. В повседневных LOB-приложениях действительно ли так много различий, чтобы гарантировать весь код, который, по-видимому, требуется для настоящего MVVM?

Ответы [ 3 ]

1 голос
/ 02 мая 2009

Вы можете использовать что-то подобное для синхронизации ваших ObservableCollections между моделью и моделью представления:

/// <summary>
/// Keeps one collection synchronised with another.
/// </summary>
/// <typeparam name="Source">The type of the source items.</typeparam>
/// <typeparam name="Destination">The type of the destination items.</typeparam>
public class CollectionSync<Source, Destination>
{
    private readonly Func<Source, Destination> _destItemFactory;
    private readonly Action<Destination>       _destItemRemover;

    private readonly IList<Destination> _destList;
    private readonly IList<Source>      _sourceList;

    /// <summary>
    /// Initializes a new instance of the <see cref="CollectionSync&lt;Source, Destination&gt;"/> class.
    /// </summary>
    /// <param name="sourceList">The source list.</param>
    /// <param name="destList">The destination list.</param>
    /// <param name="destItemFactory">Factory method which creates a Destination for a given Source.</param>
    /// <param name="destItemRemover">Method called when a Destination is removed.</param>
    public CollectionSync(IList<Source> sourceList,
                          IList<Destination> destList,
                          Func<Source, Destination> destItemFactory,
                          Action<Destination> destItemRemover)
    {
        _destItemFactory = destItemFactory;
        _destItemRemover = destItemRemover;
        _sourceList = sourceList;
        _destList = destList;

        ((INotifyCollectionChanged) _sourceList).CollectionChanged += SourceCollection_CollectionChanged;

        PopulateWithAllItems();
    }

    private void PopulateWithAllItems()
    {
        foreach (Source sourceItem in _sourceList)
            _destList.Add(_destItemFactory(sourceItem));
    }

    private void SourceCollection_CollectionChanged(object sender, NotifyCollectionChangedEventArgs args)
    {
        switch (args.Action)
        {
            case NotifyCollectionChangedAction.Add:
                OnItemsAdded(args.NewStartingIndex, args.NewItems);
                break;
            case NotifyCollectionChangedAction.Remove:
                OnItemsRemoved(args.OldStartingIndex, args.OldItems);
                break;
            case NotifyCollectionChangedAction.Reset:
                OnItemsReset();
                break;
            case NotifyCollectionChangedAction.Move:
            case NotifyCollectionChangedAction.Replace:
                throw new NotImplementedException();
        }
    }

    private void OnItemsReset()
    {
        _destList.Clear();
        PopulateWithAllItems();
    }

    private void OnItemsRemoved(int index, ICollection items)
    {
        int itemCount = items.Count;
        for (int i = 0; i < itemCount; i++)
        {
            Destination removed = _destList[index];
            _destList.RemoveAt(index);
            if (_destItemRemover != null)
                _destItemRemover(removed);
        }
    }

    private void OnItemsAdded(int index, IList items)
    {
        int itemIndex = index;
        foreach (Source item in items)
        {
            // Add to Items collection
            _destList.Insert(itemIndex, _destItemFactory(item));
            itemIndex++;
        }
    }
}

На примере Order / OrderDetails в модели представления Order вы бы подключили две ObservableCollections, например:

_modelToViewModelSync = new CollectionSync<IOrderDetail, OrderDetailViewModel>(
    orderDetailModels,                 // the list of your order details models
    OrderDetails,                      // the list of order details view models exposed by the Order view model
    x => new OrderDetailViewModel(x),  // factory method to create a view model
    null);                             // do something here if you care when your view models are removed
1 голос
/ 13 марта 2009

Похоже, это то, что вам нужно: http://jonas.follesoe.no/SpeakingAtMSDNLiveNextMonth.aspx

Перевод на Google дает это как реферат для разговора:

Silverlight 2 был выпущен этой осенью и закладывает хорошую основу для разработчиков, которые хотят создавать многофункциональные интернет-приложения (RIA) на основе. СЕТЬ. На этом занятии мы подробно расскажем о разработке и преимуществах выбора Silverlight 2 в качестве платформы для бизнес-приложений, ориентированных на данные. Сессия, помимо прочего, расскажет о доступе к данным через защищенные сервисы WCF, о том, как структурировать код с использованием шаблона Model-View-View Model (MVVM), о том, как писать код, с которым могут работать дизайнеры, и простых советах для разработчиков , Сессия будет построена вокруг приложения журнала погружений, где код будет доступен после презентации.

Однако в то же время Йонас уже говорил о MVVM здесь:

http://jonas.follesoe.no/YouCardRevisitedImplementingTheViewModelPattern.aspx

0 голосов
/ 02 мая 2009

Когда дело доходит до вопроса «Нужна ли мне другая модель представления», я отвечаю так: если все, что делает ваше представление, - это отображение данных модели, то нет никакого вреда в прямой привязке к заказу напрямую. Создание ViewModel для этого было бы очень излишним. Время, когда необходимо создать ViewModel, - это когда у вас есть логика или состояние на экране «Детали заказа», который необходимо представить. Вместо того, чтобы добавить это к модели, вы создаете ViewModel в то время.

Что касается синхронизации этих элементов, как и в GraemeF, я создал класс Binder, который использует отражение для связывания двух значений. Он синхронизирует свойства моей модели и модели представления, и его можно использовать для синхронизации других вещей, например, этой конкретной коллекции. При создании такого подшивки возникают некоторые накладные расходы, но как только это будет сделано, вы можете указать корреляции данных функциональным способом, что действительно приятно.

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