c# - 在不同类中的Property上引发PropertyChangeNotification(不同的ViewModel)

标签 c# mvvm properties inotifypropertychanged

动机:
我想要一个'File-> Save As'MenuItem,其行为类似于Visual Studio。没有打开任何内容时,它说“将所选项目另存为...”
当在标签中打开特定文件(例如SomeFile.cs)时,MenuItem会显示“将SomeFile.cs另存为...”。

我的App架构(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返回要在 Pane 标题中显示的字符串,SafeFileName仅返回路径等的文件名...

问题:
当我更改文件名(从而更改BaseProjectViewModel的属性)时,如何在RaisePropertyChanged中触发SelectedProjectNameMainWindowViewModel
什么是最干净的方法?

我的想法
我想到了两种可能的方法,但是我不知道其中是否有正确的方法:
  • (简而言之)在CollectionChanged上听_projects。当有添加/删除->订阅/ubsubscribe一个事件处理程序时,
    看看PropertyName是否是我们要寻找的那个,如果是,则随后调用RaisePropertyChanged("SelectedProjectName")
  • 使用类似MVVM Light Messaging的东西。

  • 问题2:如果您不建议任何其他方式,而实际上却建议使用这两种方式中的一种-您能否详细说明优点和缺点?

    编辑

    我创建了一个非常简单的项目来演示问题LINK
    运行项目时:
  • 'New'添加一个新的TabItem。编辑文本后,TabHeader会带有星号。
  • “保存{0}”菜单项“保存”选定的TabItem(通过删除星号模拟)。我不想使示例复杂化,并引入SaveFileDialog之类的东西。
  • “另存为{0}”菜单项模拟“另存为”,其方式是将“X”字符添加到od Tab标题字符串的末尾。

  • 当没有选择TabItem时,{0}解析为“Selected Item”。

    选择一个选项卡后,单击SaveAs()并打开菜单,您会注意到尚未对SelectedProjectName属性进行更改。当您单击另一个选项卡,然后选择第一个选项卡时,更改将被传播。

    为Erno编辑:我无法理解的是:假设我对每种文档类型都有一个特殊的菜单。假设我选择了一个特定的选项卡(启用/可见了其自己的菜单,另一个处于折叠状态)。如何帮助我将BaseProjectViewMode中PaneHeader属性的PropertyChanged传播到MainWindowViewModel中的SelectedProjectName?如果有时间,可以在示例中进行演示吗?我也想问你,如果我想/需要做布线,那是另一种选择?先感谢您。

    最佳答案

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

    选项#2可能还可以,但最终可能会导致与#1相同的布线困惑,但由于消息传递,它的可见性将降低。

    我会考虑另一种方法:

  • 在MainWindow中放置一个菜单,该菜单负责在未打开或未选择任何文件时处理命令。
  • 在 View 中打开文档并具有焦点时的
  • :用文档特定菜单替换当前菜单中的。 (例如MDI应用程序在WinForms中工作)

  • 这样,您可以针对每个文档(类型)自定义菜单,并且不需要事件相关性。

    关于c# - 在不同类中的Property上引发PropertyChangeNotification(不同的ViewModel),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18460779/

    相关文章:

    c# - XML 序列化是否需要读/写属性?

    c# - 在新浏览器选项卡中查看 PDF 文档

    c# - WPF 功能区 : DataTemplate causes BindingExpression path error

    C# 函数指针

    wpf - 使用 MVVM 使用 Caliburn Micro 关闭所有子窗口

    c# - 如何基于绑定(bind)列表构建包含其他控件的 WPF 控件

    c# - 没有类型的 IEnumerable 属性

    c# - 将文件(字节数组)的字符串表示形式转换回 C# 中的文件

    c# - WPF:仅在命令可以执行时才应用DataTemplate-Style

    python - @property 装饰器在 Python 中是如何工作的?