假设我有一个OrderModel和一个OrderViewModel。我在ViewModel和Model上都有供应商,订单日期等属性,并且它们是相互关联的。看到这方面的例子并且似乎足够直截了当,尽管在编写setter / getter方面有些重复。
现在我如何处理OrderDetails?在我的模型中,我会有一个List。
OrderDetail是否有OrderDetailViewModel?如果是这样,那么OrderViewModel是如何提供的呢?作为ObservableCollection?如果是这样,你如何保持与原始列表同步?
这是我没有看到一个体面的例子。如果有人可以指出我,我会很感激。我嘲笑MVVM的概念,但我开始认为它是一个很大的开销。为什么不让ViewModel处理模型部分。在日常的LOB应用程序中,两者之间真的有很大差异,以保证真正的MVVM似乎需要的所有代码吗?
答案 0 :(得分:1)
看起来这就是您所需要的:http://jonas.follesoe.no/SpeakingAtMSDNLiveNextMonth.aspx
谷歌上的翻译将此作为谈话的摘要:
Silverlight 2于今年秋季发布,为希望创建基于的富Internet应用程序(RIA)的开发人员奠定了良好的基础。净。在本次会议中,我们深入了解了Silverlight 2中的开发以及选择Silverlight 2作为以数据为中心的业务应用程序平台的好处。本次会议将讨论通过安全的WCF服务进行数据访问,如何使用模型 - 视图 - 模型模式(MVVM)构建代码,如何编写代码,设计人员可以使用以及为开发人员提供easy-Blend技巧。该会话将围绕潜水日志应用程序构建,其中代码将在演示后可用。
然而,同时Jonas已经在这里讨论过MVVM:
http://jonas.follesoe.no/YouCardRevisitedImplementingTheViewModelPattern.aspx
答案 1 :(得分:1)
您可以使用类似的东西来保持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<Source, Destination>"/> 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
答案 2 :(得分:0)
当谈到“我是否需要另一个视图模型”这个问题时,我的答案是这样的:如果您所有的视图都在显示模型数据,那么直接绑定到订单没有任何害处。为此创建ViewModel将非常多余。需要创建ViewModel的时间是在“订单详细信息”屏幕中有逻辑或状态需要表示的时间。您可以在此时创建ViewModel,而不是将其添加到模型中。
就保持这些项目同步而言,与GraemeF类似,我创建了一个Binder类,它使用反射将两个值绑定在一起。它使我的模型和视图模型属性保持同步,并且它可以用于使其他事物保持同步,就像这个特定的集合一样。创建这样的绑定器有一些开销,但一旦完成,您可以以功能方式指定数据关联,这非常好。