在不同的类(不同的ViewModel)上提升属性的PropertyChangeNotification

时间:2013-08-27 08:39:14

标签: c# mvvm properties inotifypropertychanged

动机:
我想要一个'File->另存为'MenuItem,其行为与Visual Studio中的行为相同。当没有任何东西打开时,它会显示“将所选项目另存为......” 当标签中打开特定文件(例如SomeFile.cs)时,MenuItem会将“SomeFile.cs保存为...”。


我的应用架构(MVVM,使用MVVM Light):

MainWindow.xaml:

<MenuItem Header="{Binding SelectedProjectName}" HeaderStringFormat="Save {0} As..." />

MainWindowViewModel:

我拥有一组已打开的标签(已打开的文件)

private ObservableCollection<BaseProjectViewModel> _projects;

我有一个返回当前所选标签的属性

public BaseProjectViewModel SelectedProject
{
    get
    {
        return _selectedProject;
    }
    set
    {
        if (_selectedProject == value)
        {
            return;
        }
        _selectedProject = value;
        RaisePropertyChanged("SelectedProject");
        RaisePropertyChanged("SelectedProjectName");
    }
}

我创建了一个属性,返回当前所选标签中文件的名称

public string SelectedProjectName
{
    get
    {
        if (SelectedProject == null)
        {
            return "Selected Item";
        }
        return SelectedProject.SafeFileName;
    }
}

BaseProjectViewModel用作各种文件类型的基类。每种文件类型都有自己的派生自BaseProjectViewModel的类。它具有类似的属性 PaneHeader返回要在窗格标题中显示的字符串, SafeFileName仅返回路径的文件名等...

问题:
当我更改文件名(因此更改BaseProjectViewModel的属性)时,如何触发RaisePropertyChangedSelectedProjectName的{​​{1}}? 最干净的方法是什么?

我的想法
我想到了两种可能的方法,但我不知道它们中是否有正确的方法:

  1. (简而言之)在MainWindowViewModel上聆听CollectionChanged。当有添加/删除 - &gt; subscribe / ubsubscribe一个事件处理程序 查看PropertyName是否是我们要查找的那个,如果是,则随后致电_projects

  2. 使用RaisePropertyChanged("SelectedProjectName")

  3. 之类的内容

    问题2:如果您没有提出任何其他方式,事实上您会建议其中一种 - 请您详细说明优缺点?


    修改

    我创建了一个非常简单的项目来演示问题 - LINK。 运行项目时:

    • '新'添加了一个新的TabItem。编辑文本时,TabHeader将用星号装饰。
    • '保存{0}'菜单项“保存”选定的TabItem(通过删除星号模拟)。我不想让这个例子复杂化并引入一个SaveFileDialog等。
    • '另存为{0}'菜单项模拟另存为,以便将“X”字符添加到结尾标签标题字符串。

    如果未选择TabItem,则{0}将解析为“选定项目”。

    如果选择了一个选项卡,则单击SaveAs()并打开菜单,您将注意到尚未在SelectedProjectName属性上引发更改。当您单击另一个选项卡然后选择第一个选项卡时,将传播更改。

    编辑Erno :我无法理解的是:我们假设每个文档类型都有一个特殊菜单。假设我选择了一个特定的选项卡(其自己的菜单已启用/可见,另一个已折叠)。它是如何帮助我将BaseProjectViewMode中的PaneHeader属性的PropertyChanged传播到MainWindowViewModel中的SelectedProjectName?如果您有时间,请在示例中进行演示吗?我还想问你,如果我想要/ neede做接线,会有什么替代方法?提前谢谢。

1 个答案:

答案 0 :(得分:0)

根据您的选择,我不喜欢#1,因为它可能会引入很多难以跟踪和维护的布线。

选项#2可能没问题,但最终会出现与#1相同的布线混乱,但由于消息传递不太明显。

我会考虑另一种方法:

  • 在MainWindow中放置一个菜单,负责在没有打开或选择文件时处理命令。
  • 在视图中打开文档并具有焦点时:用文档特定菜单替换当前菜单。 (就像MDI应用程序在WinForms中工作)

这样,您可以自定义每个文档的菜单(类型),并且不需要事件依赖性。