【问题标题】:ObservableCollection event propagation and correct usage in MVVMMVVM 中的 ObservableCollection 事件传播和正确使用
【发布时间】:2016-04-11 11:22:22
【问题描述】:

我正在进入 MVVM 并从 Prism 框架开始,在我的示例应用程序中我有典型的导航。其中一页应该列出一些应用程序,我想知道实现中的差异。为简单起见,这里有一些来自代码的小 sn-ps:

应用模型

public class Application : BindableBase
{
    private string _commandLine;
    private string _name;
    private string _smallIconSource;

    public string CommandLine
    {
        get { return _commandLine; }
        set { SetProperty(ref _commandLine, value); }
    }

    public string Name
    {
        get { return _name; }
        set { SetProperty(ref _name, value); }
    }

    public string SmallIconSource
    {
        get { return _smallIconSource; }
        set { SetProperty(ref _smallIconSource, value); }
    }
}

ApplicationPage 视图模型

public class ApplicationPageViewModel : BindableBase
{
    private ObservableCollection<Application> _applicationCollection;

    public ApplicationPageViewModel()
    {
        // load some collection entries here
    }

    public ObservableCollection<Application> ApplicationCollection
    {
        get { return _applicationCollection; }
        set
        {
            // if (_applicationCollection != null)
            //     _applicationCollection.CollectionChanged -= ApplicationCollectionChanged;
            SetProperty(ref _applicationCollection, value);
            // if (_applicationCollection != null)
            //     _applicationCollection.CollectionChanged += ApplicationCollectionChanged;
        }
    }
}

应用程序页面视图

<!-- ... -->
<ItemsControl ItemsSource="{Binding ApplicationCollection}">
    <ItemsControl.ItemsPanel>
        <ItemsPanelTemplate>
            <StackPanel Orientation="Vertical" />
        </ItemsPanelTemplate>
    </ItemsControl.ItemsPanel>
    <ItemsControl.ItemTemplate>
        <DataTemplate>
            <!-- some kind of representation of applications -->
            <Label Content="{Binding Name}" />
        </DataTemplate>
    </ItemsControl.ItemTemplate>
</ItemsControl>
<!-- ... -->

在互联网上的一些代码示例中,尤其是在 SO 上的一些问题中,我看到人们问是否要存储 ViewModels 的 ObservableCollection 而不是像我那样存储模型 - 此时我很好奇你什么时候选择哪个版本优于另一个?

此外,我很想知道Application 类中的更改是否反映在ApplicationPageViewModel 类中,或者我是否必须挂钩CollectionChanged 事件(从我看到这种技术的Brian Lagunas 网络研讨会中可以看出) .到目前为止,我只在CollectionChanged 事件中看到了这个钩子,如果DelegateCommands 手动调用RaiseCanExecuteChanged 方法,以防止在具有以下RelayCommands 实现时出现不必要的膨胀/调用:

public event EventHandler CanExecuteChanged
{
    add { CommandManager.RequerySuggested += value; }
    remove { CommandManager.RequerySuggested -= value; }
}

【问题讨论】:

  • 您的问题基本上是如何通知项目有关它们所在的集合已更改。我可以想到:1)将 ViewModel 实例传递给每个项目(构造函数或其他),项目可以订阅 ViewModel 的某些事件,事件由 ViewModel(甚至由项目)引发 2)ViewModel 处理所有更改和通知(通过调用收集更改的每个项目方法)。如果您实现INotifyPropertyChanged(这就是您将要收听的事件),则会给出方法(1)。

标签: c# wpf mvvm observablecollection inotifypropertychanged


【解决方案1】:

如果您的集合中的属性发生变化,我会使用 ViewModels。如果一个项目上的数据没有改变,那么如果你使用虚拟机或模型并没有什么不同,这只是你喜欢的方式。 我个人喜欢将我的模型包装在 ViewModels 中,因为我可以轻松添加组合属性以进行显示,而我不想直接在我的模型中使用这些属性。

如果您想在应用程序更改时对 ApplicationPageViewModel 执行一些操作,则必须

  • 为应用程序使用 ViewModel
  • 连接每个应用程序视图模型的 INotifyPropertyChanged 事件
  • 每次添加新应用程序时,还要将侦听器添加到此应用程序

如果您只想在添加或删除应用程序时执行一些操作,则不必使用 ViewModel,只需注册 ObservableCollection 的 CollectionChanged 事件

【讨论】:

  • 好吧,这清除了一些东西。我仍然想知道你是否使用 ViewModels 来包含一些你肯定依赖于 Facade 模式的组合属性,不是吗?这种方法不会使可维护性变得更加复杂,并迫使您编写重复的代码来访问您不想隐藏的相同属性吗?
  • 对于我当前的项目,我为 ViewModels 使用 DynamicObject 包装器,我只想添加一些属性或视图相关功能。这不是最快的方法,但非常方便,因为我不必为属性复制代码,而只需为 ViewModel 分配模型。对于我的模型,我无法注册更改,因为它没有实现 INotifyPropertyChanged 接口,但只保存数据。
  • 除了 INotifyPropetryChanged 之外,如果 ObservableCollections 中有 ObvservableCollections,有时还需要添加 PropertyChanged => OnCollectionChanged。我尝试将其自动化,但没关系,手动实现它很简单直接。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-12-31
  • 2015-04-14
  • 2013-09-18
  • 2014-06-26
相关资源
最近更新 更多