基于WPF和MVVM模式中的嵌套模型实体构建ViewModel

BFi*_*Fil 12 wpf nested mvvm viewmodel

我在理解如何基于以下模型构建视图模型时遇到问题

(我将模型简化为更清晰)

public class Hit
{
   public bool On { get; set;}
   public Track Track { get; set; }
}
public class Track
{
   public ObservableCollection<Hit> Hits { get; set; }
   public LinearGradientBrush Color { get; set; }
   public Pattern Pattern { get; set; }
}
public class Pattern
{
   public string Name { get; set; }
   public ObservableCollection<Tracks> Tracks { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

现在,我的问题是,如何构建ViewModels ..

我需要通过模型保持原始关系,beacaus我在Pattern上有一个Serialize()方法,将它序列化为XML文件..(带有相关的Tracks和Hits)

为了能够将模式绑定到用户控件和它的嵌套模板,我还应该有一个带有ObservableCollection <TrackViewModel>的PatternViewModel,对于TrackViewModel和HitViewModel来说也是如此...我需要在查看不属于业务对象的模型(颜色和更多..)

在视图模型上复制模型的所有关系对我来说似乎不是一件好事......并且在编写视图模型时跟踪所有这些关系也更容易出错.

谁有更好的方法/解决方案?

BFi*_*Fil 2

我最终使用了 Joe White 建议的部分解决方案,但方式略有不同

解决方案是让模型保持在开始时的样子,并将内部集合的 CollectionChanged 事件处理程序附加到集合,例如,PatternViewModel 将是:

public class PatternViewModel : ISerializable
{
    public Pattern Pattern { get; set; }
    public ObservableCollection<TrackViewModel> Tracks { get; set; }

    public PatternViewModel(string name)
    {
        Pattern = new Pattern(name);
        Tracks = new ObservableCollection<TrackViewModel>();
        Pattern.Tracks.CollectionChanged += new NotifyCollectionChangedEventHandler(Tracks_CollectionChanged);
    }

    void Tracks_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
    {
        switch (e.Action)
        {
            case NotifyCollectionChangedAction.Add:
                foreach (Track track in e.NewItems)
                {
                    var position = Pattern.Tracks.IndexOf((Track) e.NewItems[0]);
                    Tracks.Insert(position,new TrackViewModel(track, this));
                }
                break;
            case NotifyCollectionChangedAction.Remove:
                foreach (Track track in e.OldItems)
                    Tracks.Remove(Tracks.First(t => t.Track == track));
                break;
            case NotifyCollectionChangedAction.Move:
                for (int k = 0; k < e.NewItems.Count; k++)
                {
                    var oldPosition = Tracks.IndexOf(Tracks.First(t => t.Track == e.OldItems[k]));
                    var newPosition = Pattern.Tracks.IndexOf((Track) e.NewItems[k]);
                    Tracks.Move(oldPosition, newPosition);
                }
                break;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

所以我可以在视图模型上附加新的颜色/样式/命令,以保持我的基本模型干净

每当我在基本模型集合中添加/删除/移动项目时,视图模型集合都会保持彼此同步

幸运的是,我不必在应用程序中管理大量对象,因此重复的数据和性能不会成为问题

我不太喜欢它,但它工作得很好,而且工作量不是很大,只是包含其他视图模型集合的视图模型的事件处理程序(在我的例子中,一个用于 PatternViewModel 同步 TrackViewModels,另一个用于同步 TrackViewModels)在 TrackViewModel 上管理 HitViewModel)

仍然对您的想法或更好的想法感兴趣=)