【问题标题】:How to keep collections of viewmodels and models in sync如何使视图模型和模型的集合保持同步
【发布时间】:2010-01-26 11:29:10
【问题描述】:

我正在使用 wpf 工具包数据网格来显示 AccountViewModel 的可观察集合。

问题是当我从网格中删除一个帐户时,我希望将其从 ObservableCollection 中删除 - 为用户提供视觉反馈,但我希望 Account 模型的基础列表保持不变,只需使用“IsDeleted”在 Account 模型上设置的标志。

然后,无论何时提交更改,我的服务都知道要在数据库中添加/更新或删除哪些帐户。

我正在订阅 CollectionChanged 事件:

AccountViewModels.CollectionChanged += AccountsChanged;

然后在删除某些内容时将视图模型的模型 isdeleted 标志设置为 true:

private void AccountsChanged(object sender, NotifyCollectionChangedEventArgs e)
    {
        if (e.NewItems != null)
        {
            foreach (AccountViewModel model in e.NewItems)
            {
                model.PropertyChanged += accountPropertyChanged;
                model.Account.IsNew = true;
            }
        }
        if (e.OldItems != null)
        {

            foreach (AccountViewModel model in e.OldItems)
            {
                model.PropertyChanged -= accountPropertyChanged;
                model.Account.IsDeleted = true;
            }
        }
    }

但显然这会将其从可观察集合中删除。因此,当我提交更改时,将没有设置 IsDeleted 标志的帐户。即它们已经被删除了。

 foreach (AccountViewModel acc in m_ViewModel.AccountViewModels)
        {
            WorkItem workItem = null;
            if(acc.Account.IsNew)
                workItem = new WorkItem("Saving new account: " + acc.AccountName, "Saving new account to the database", () => Service.AddAccount(acc.Account));
            else if (acc.Account.IsDeleted)
                workItem = new WorkItem("Removing account: " + acc.AccountName, "Setting account inactive in the database", () => Service.RemoveAccount(acc.Account));
            else if(acc.Account.IsDirty)
                workItem = new WorkItem("Updating account: " + acc.AccountName, "Updating account in the database", () => Service.UpdateAccount(acc.Account));

            workItems.Add(workItem);

        }

这是否意味着我需要维护两个列表,一个是帐户模型列表,另一个是可观察的帐户视图模型集合?这看起来很讨厌,必须有更好的方法来做到这一点。

【问题讨论】:

    标签: wpf viewmodel observablecollection


    【解决方案1】:

    我认为使用 ObservableCollection 可以做到这一点再好不过了,因为该类拥有自己的内部对象列表。

    但是,如果您实现了一个实现 INotifyCollectionChanged 和 INotifyPropertyChanged 的​​自定义集合,您可以让它包装和过滤您的源集合。

    它可以过滤 IsDeleted 标志,使它们不可见。

    每当用户删除项目时,您都可以直接修改域模型,将 IsDeleted 标志设置为 true。但是,您仍然需要一个事件机制来引发适当的事件,但使用这种方法,您只有一个项目集合。

    自定义集合只是域模型上的投影,并添加了事件。

    【讨论】:

    • 如果我走这条路,当我的模型中的一个字段在网格中被编辑时,我如何捕获属性更改事件。我真的不希望我的域模型必须实现 INotifyPropertyChanged,这是我的视图模型之前所做的事情。
    • 这就是我说你需要有一些事件机制的意思。您可以从域模型中引发事件(它不需要是 INotifiedPropertyChanged - 它可以是自定义事件),或者您需要明确通知 Projecting Collection 有关更改,以便它可以引发正确的事件。第三种选择是让 Projecting Collection 轮询底层模型的变化,但这条路线充满了危险......
    【解决方案2】:
    猜你喜欢
    • 2012-12-04
    • 2011-06-21
    • 1970-01-01
    • 2011-06-06
    • 1970-01-01
    • 2013-03-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多