2

所以可以说我有一个 OrderModel 和一个 OrderViewModel。我在 ViewModel 和 Model 上都有供应商、订单日期等属性,它们是链接在一起的。看过这方面的例子,看起来很简单,尽管在编写 setter/getter 方面有些重复。

现在我该如何处理 OrderDetails?在我的模型中,我会有一个列表。

我有 OrderDetail 的 OrderDetailViewModel 吗?如果是这样,那么 OrderViewModel 是如何提供的呢?作为 ObservableCollection?如果是这样,您如何使其与原始列表保持同步?

这是我没有看到一个像样的例子的地方。如果有人可以指出我,我将不胜感激。我喜欢 MVVM 的概念,但我开始觉得它的开销太大了。为什么不让 ViewModel 也处理模型部分。在日常的 LOB 应用程序中,两者之间真的有那么大的区别来保证真正的 MVVM 似乎需要的所有代码吗?

4

3 回答 3

1

看起来这是您需要的:http: //jonas.follesoe.no/SpeakingAtMSDNLiveNextMonth.aspx

谷歌上的翻译将此作为演讲的摘要:

Silverlight 2 于今年秋季发布,为想要在此基础上创建富 Internet 应用程序 (RIA) 的开发人员奠定了良好的基础。网。在本次会议中,我们将深入了解 Silverlight 2 的发展以及选择 Silverlight 2 作为以数据为中心的业务应用程序平台的好处。本次会议将涵盖通过安全 WCF 服务进行数据访问、如何使用模型-视图-视图模型模式 (MVVM) 构建代码、如何编写代码、设计人员可以使用以及为开发人员提供易于混合的技巧等内容. 会议将围绕潜水日志应用程序构建,演示后代码将可用。

然而与此同时,Jonas 已经在这里谈到了 MVVM:

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

于 2009-03-13T06:54:52.383 回答
1

You can use something like this to keep your ObservableCollections synchronised between the model and view model:

/// <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++;
        }
    }
}

Taking your Order/OrderDetails example, in your Order view model you would hook up the two ObservableCollections like this:

_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
于 2009-05-01T20:04:37.190 回答
0

当谈到“我是否需要另一个视图模型”这个问题时,我的回答是:如果您的视图所做的只是显示模型数据,那么直接绑定到订单并没有什么坏处。为此创建一个 ViewModel 将是非常多余的。需要创建 ViewModel 的时间是当您在“订单详细信息”屏幕中有需要表示的逻辑或状态时。不是将它添加到模型中,而是在那时创建一个 ViewModel。

至于保持这些项目同步,类似于 GraemeF,我创建了一个 Binder 类,它使用反射将两个值绑定在一起。它使我的模型和视图模型属性保持同步,并且可用于使其他事物保持同步,例如这个特定的集合。创建这样的活页夹有一些开销,但是一旦完成,您就可以以函数方式指定数据相关性,这非常好。

于 2009-05-01T20:13:07.200 回答