首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >与“实时”集合和属性同步的双向视图模型

与“实时”集合和属性同步的双向视图模型
EN

Stack Overflow用户
提问于 2010-02-05 21:12:06
回答 5查看 3.3K关注 0票数 7

最近,我对View Models (VM)的看法有些不太对劲。

就像this guy一样,我得出的结论是,我需要在VM上公开的集合通常包含与在业务对象上公开的集合不同的类型。

因此,这两种类型之间必须存在双向映射或转换。(让事情更复杂的是,在我的项目中,这个数据是“实时的”,这样只要你改变一个属性,它就会被传输到其他计算机上)

我几乎可以使用像Truss这样的框架来处理这个概念,尽管我怀疑其中会有一个令人讨厌的惊喜。

不仅必须转换对象,还需要在这两个集合之间进行同步。(让事情更复杂的是,我可以考虑VM集合可能是业务对象集合的子集或联合的情况,而不是简单的1:1同步)。

我可以看到如何做一个单向的“实时”同步,使用一个复制的ObservableCollection或类似CLINQ的东西。

然后问题就变成了:创建/删除项目的最佳方式是什么?

双向同步似乎不在卡片上--我没有找到这样的例子,唯一一个远程支持这样的东西的类是ListCollectionView。将双向同步添加回业务对象集合是一种明智的方式吗?

我见过的所有样本似乎都没有解决过如此“复杂”的问题。

所以我的问题是:你如何解决这个问题?有没有什么技术可以更新VM中的模型集合?对此最好的通用方法是什么?

EN

回答 5

Stack Overflow用户

回答已采纳

发布于 2010-02-10 05:26:57

我也在为通过MVVM使用WPF的两个集合的双向同步而苦苦挣扎。关于这个问题,我在MVVM: To Wrap or Not to Wrap? How much should the ViewModel wrap the Model? (Part 1)MVVM: To Wrap or Not to Wrap? Should ViewModels wrap collections too? (Part 2)上发了博客,包括一些显示双向同步的示例代码。然而,正如帖子中指出的那样,实现并不理想。我会将其限定为概念证明。

我喜欢Alex_P发布的BLINQCLINQObtics框架。这是一种很好的方法来获得同步行为的一面。也许另一边(从VM到Model)可以通过另一条路径实现?我刚刚在我的博客上发布了part 3,讨论了其中的一些内容。

在我看来,在LINQ语句将数据投影到新结构的情况下,不支持通过BLINQ和CLINQ进行双向。

但是,在LINQ查询返回与基础集合相同的数据类型的情况下,看起来CLINQ可能支持双向同步。这更像是一种过滤场景,与ViewModel包装模型中数据的用例不匹配。

票数 3
EN

Stack Overflow用户

发布于 2010-02-06 00:22:41

就我个人而言,我在我的模型和视图模型中使用ObservableCollection。

代码语言:javascript
复制
class Model
{
    public ObservableCollection<Foo> Foos;
}

class ViewModel
{
    public Model Model;
    public ObservableCollection<FooView> Foos;

    public ViewModel()
    {
        Model.Foos.CollectionChanged += OnModelFoosCollection_CollectionChanged;
    }

    void OnModelFoosCollection_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
    {
       Foo re;

       switch (e.Action)
       {
          case NotifyCollectionChangedAction.Add:
             re = e.NewItems[0] as Foo;
             if (re != null)
                AddFoo(re);  //For other logic that may need to be applied
             break;
          case NotifyCollectionChangedAction.Remove:
             re = e.OldItems[0] as Foo;
             if (re != null)
                RemoveFoo(re); 
             break;
          case NotifyCollectionChangedAction.Reset:
             Foos.Clear();
             /* I have an AddRange in an ObservableCollection-derived class
                You could do Model.Foo.ForEach(ree => AddFoo(ree));
             */
             var converter = 
                from ree in Model.Foo
                select new FooView(ree);
             Reports.AddRange(converter); 
             break;
          default:
             //exercise for the reader :)
             s_ILog.Error("OnModelFoosCollection_CollectionChangedDid not deal with " + e.Action.ToString()); 
             break;
       }
    }   

    void AddFoo(Foo f)
    {
        Foos.Add(new FooView(f));
    }

    void RemoveFoo(Foo f)
    {
       var match = from f in Foos
          where f.Model == f  //if you have a unique id, that might be a faster comparison
          select f;
       if(match.Any())
          Foos.Remove(match.First());
    }
}

现在,当您从Model的Foo集合中删除某些内容时,它将自动删除相应的FooView。这与我对这类事情的看法一致。如果我想删除一些东西,Model才是真正需要删除的地方。

这感觉像是有很多代码,但实际上并不是那么多。我相信可以构建一个通用的版本,但我想你最终总是想要处理添加/删除元素的自定义逻辑。

票数 4
EN

Stack Overflow用户

发布于 2010-02-16 07:09:10

我已经编写了一些帮助器类,用于在视图模型对应的here中包装业务对象的可观察集合,也许应该将其扩展为另一种方式。总是在寻找贡献...

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/2207373

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档