Наборы синхронизации MVVM

Это - конкретный Linux, но Вы могли использовать:

SELF=$(readlink /proc/$/fd/255)
45
задан Jake Pearson 10 August 2009 в 20:29
поделиться

6 ответов

Я не могу точно понять ваши требования, однако способ, которым я справился с подобной ситуацией, использовать событие CollectionChanged в ObservableCollection и просто создавать / уничтожать модели представления по мере необходимости.

void OnApplesCollection_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{    
  // Only add/remove items if already populated. 
  if (!IsPopulated)
    return;

  Apple apple;

  switch (e.Action)
  {
    case NotifyCollectionChangedAction.Add:
      apple = e.NewItems[0] as Apple;
      if (apple != null)
        AddViewModel(asset);
      break;
    case NotifyCollectionChangedAction.Remove:
      apple = e.OldItems[0] as Apple;
      if (apple != null)
        RemoveViewModel(apple);
      break;
  }

}

Могут возникнуть некоторые проблемы с производительностью при добавлении / удалении большого количества элементов в ListView.

Мы решили эту проблему следующим образом: Расширение коллекции ObservableCollection для добавления методов AddRange, RemoveRange, BinaryInsert и добавление событий, которые уведомляют других об изменении коллекции. Вместе с расширенным CollectionViewSource, который временно отключает источник при изменении коллекции, он отлично работает.

HTH,

Деннис

9
ответ дан 26 November 2019 в 21:16
поделиться

Ну, во-первых, я не думаю, что есть единственный «правильный способ» сделать это. Это полностью зависит от вашего приложения. Есть способы более правильные и менее правильные.

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

void CreateNewCustomer()
{
    Customer newCustomer = Customer.CreateNewCustomer();
    CustomerViewModel workspace = new CustomerViewModel(newCustomer, _customerRepository);
    this.Workspaces.Add(workspace);
    this.SetActiveWorkspace(workspace);
}

Мне интересно, что мешает вам создавать AppleModelView каждый раз, когда вы создаете Apple ? Мне кажется, что это самый простой способ «синхронизировать» эти коллекции, если только я не понял ваш вопрос неправильно.

4
ответ дан 26 November 2019 в 21:16
поделиться

Я использую лениво сконструированные, автоматически обновляемые коллекции:

public class BasketModelView
{
    private readonly Lazy<ObservableCollection<AppleModelView>> _appleViews;

    public BasketModelView(BasketModel basket)
    {
        Func<AppleModel, AppleModelView> viewModelCreator = model => new AppleModelView(model);
        Func<ObservableCollection<AppleModelView>> collectionCreator =
            () => new ObservableViewModelCollection<AppleModelView, AppleModel>(basket.Apples, viewModelCreator);

        _appleViews = new Lazy<ObservableCollection<AppleModelView>>(collectionCreator);
    }

    public ObservableCollection<AppleModelView> Apples
    {
        get
        {
            return _appleViews.Value;
        }
    }
}

Используя следующие ObservableViewModelCollection:

namespace Client.UI
{
    using System;
    using System.Collections.Generic;
    using System.Collections.ObjectModel;
    using System.Collections.Specialized;
    using System.Diagnostics.Contracts;
    using System.Linq;

    public class ObservableViewModelCollection<TViewModel, TModel> : ObservableCollection<TViewModel>
    {
        private readonly ObservableCollection<TModel> _source;
        private readonly Func<TModel, TViewModel> _viewModelFactory;

        public ObservableViewModelCollection(ObservableCollection<TModel> source, Func<TModel, TViewModel> viewModelFactory)
            : base(source.Select(model => viewModelFactory(model)))
        {
            Contract.Requires(source != null);
            Contract.Requires(viewModelFactory != null);

            this._source = source;
            this._viewModelFactory = viewModelFactory;
            this._source.CollectionChanged += OnSourceCollectionChanged;
        }

        protected virtual TViewModel CreateViewModel(TModel model)
        {
            return _viewModelFactory(model);
        }

        private void OnSourceCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
        {
            switch (e.Action)
            {
            case NotifyCollectionChangedAction.Add:
                for (int i = 0; i < e.NewItems.Count; i++)
                {
                    this.Insert(e.NewStartingIndex + i, CreateViewModel((TModel)e.NewItems[i]));
                }
                break;

            case NotifyCollectionChangedAction.Move:
                if (e.OldItems.Count == 1)
                {
                    this.Move(e.OldStartingIndex, e.NewStartingIndex);
                }
                else
                {
                    List<TViewModel> items = this.Skip(e.OldStartingIndex).Take(e.OldItems.Count).ToList();
                    for (int i = 0; i < e.OldItems.Count; i++)
                        this.RemoveAt(e.OldStartingIndex);

                    for (int i = 0; i < items.Count; i++)
                        this.Insert(e.NewStartingIndex + i, items[i]);
                }
                break;

            case NotifyCollectionChangedAction.Remove:
                for (int i = 0; i < e.OldItems.Count; i++)
                    this.RemoveAt(e.OldStartingIndex);
                break;

            case NotifyCollectionChangedAction.Replace:
                // remove
                for (int i = 0; i < e.OldItems.Count; i++)
                    this.RemoveAt(e.OldStartingIndex);

                // add
                goto case NotifyCollectionChangedAction.Add;

            case NotifyCollectionChangedAction.Reset:
                Clear();
                for (int i = 0; i < e.NewItems.Count; i++)
                    this.Add(CreateViewModel((TModel)e.NewItems[i]));
                break;

            default:
                break;
            }
        }
    }
}
64
ответ дан 26 November 2019 в 21:16
поделиться

Я написал несколько вспомогательных классов для обертывания наблюдаемых коллекций бизнес-объектов в их аналогах модели представления здесь

0
ответ дан 26 November 2019 в 21:16
поделиться

Вы также можете найти пример (и пояснения) здесь: http://blog.lexique-du-net.com/index.php ? post / 2010/03/02 / MV-VM-How-to-keep-collections-of-ViewModel-and-Model-in-sync

Надеюсь на эту помощь

4
ответ дан 26 November 2019 в 21:16
поделиться

Мне очень нравится решение 280Z28. Всего одно замечание. Нужно ли делать циклы для каждого NotifyCollectionChangedAction? Я знаю, что в документах для действий указано «один или несколько элементов», но, поскольку сам ObservableCollection не поддерживает добавление или удаление диапазонов, я думаю, этого никогда не произойдет.

0
ответ дан 26 November 2019 в 21:16
поделиться
Другие вопросы по тегам:

Похожие вопросы: