【问题标题】:WPF Bind different commands to button/menuitemWPF 将不同的命令绑定到按钮/菜单项
【发布时间】:2013-07-01 13:20:48
【问题描述】:

我想请教您的意见。

我正在处理的应用程序有一个docking control,应该支持使用不同的“文档”。因此可以同时打开多个windows(tabs)。

每个都可以承载不同的内容。我提到的“文件”可能是一个文本文件, 正在开发此应用程序的 Excel 样式表或主控件(地理数据可视化)。

我正在使用MVVM 模式和 MVVM Light 库。注意:我有 Excel 电子表格的第三方控件。

现在我有一个menu bar 和一个toolbar,其中我有常见的menuitems(在menubar)/按钮(在toolbar),如“保存”、“剪切”、“复制”等。 .. 在选项卡之间切换时,“保存”按钮应调用适当的保存功能。

剪切/复制/粘贴也是如此:

  • 在带有文本文档的选项卡中 - 剪切/复制/粘贴应该对文本进行操作(为此有 wpf 内置命令)。

  • 在主控件中 - 它应该与图形元素一起使用(我必须实现这些)

  • 在电子表格中时 - 它应该与电子表格控件的随附第三方命令一起使用。

此外,可以有一个选项卡选择了一些文本 - 因此切换到此选项卡时应该启用用于剪切/复制的菜单项/按钮,而其他一些选项卡没有选择图形元素,因此用于剪切的菜单项/按钮切换到此选项卡时应禁用 /copy。

通过保存command,我可以想象一种可能的方法,但我仍然不确定这是否是实现它的好方法:在 MainWindowViewModel 中有一个RelayCommand

public ICommand SaveCommand
{
    get
    {
        if (_saveCommand == null)
        {
            _saveCommand = new RelayCommand(() => this.SaveFile());
        }
        return _saveCommand;
    }
}

并且SaveFile() 方法会在selected 选项卡的datacontext 上调用其他一些“保存方法”(这将是相应“文档”类型的视图模型)。

但是我不知道如何启用/禁用保存按钮/菜单项,而且我对如何实现不同的剪切/复制/粘贴功能一无所知。

对于问题的长度,我深表歉意。也许我可以问:

“如何根据选择/激活应用程序的哪个部分将不同的剪切/复制/粘贴命令绑定到按钮?”。

但我觉得我正在努力实现的附加背景将有助于回答这个问题。

【问题讨论】:

  • 我会让 MainViewModel 拥有其他视图模型的集合,并为当前选定的视图模型添加一个属性。然后保存命令只是将调用转发到当前选定的视图模型保存命令/方法。

标签: c# wpf mvvm binding command


【解决方案1】:

并且 SaveFile() 方法会在 所选选项卡的数据上下文(这将是 根据“文档”类型)。

SaveFile 应该由 ViewModel 实现,而不需要返回 View。

创建多个 ViewModel 来表示不同类型的文档,并让每个视图模型实现其保存功能。

视图可以使用命令的 CanExecute 方法来决定是否应启用菜单项或按钮。您只需要在 ViewModel 中实现 CanExecute 方法即可。在大多数情况下,Save 命令的 CanExecute 会使用 IsDirty 或类似属性。

编辑

对于应该知道上下文/活动选项卡项的菜单项,您可以创建一个主 ViewModel,其中包含菜单命令和一组 ViewModel(每个选项卡项一个)

在上下文感知菜单项的命令处理程序中,获取活动的 ViewModel 并传递命令。

要获取当前的 TabItem,请将 SelectedItem 绑定到主 ViewModel 的属性(属性的类型可以是 ViewModel 的基类)。

这样,您无需返回视图即可获取当前选项卡项。

【讨论】:

  • 当视图的数据上下文(选定选项卡)是相应的视图模型(每种文档类型一个类型)时,我不明白代码在哪里返回视图?你是什​​么意思?在视图模型中,我需要以某种方式找出选择了哪个选项卡。到目前为止,我能够做到这一点的唯一方法是循环浏览集合(我持有参考)并找到选定的选项卡。但你可能是对的,应该有另一种方法来找出当前选择的视图。您能否也帮我解决问题的剪切/复制部分?然后我可以将您的答案标记为已接受。
  • 请参阅我的答案。
  • 刚刚发现我正在使用的控件(Telerik 对接)不支持 SelectedItem(或类似于 AvalonDock 中的 ActiveDocument)。它有object SelectedContentRadPane SelectedPane - 我可以做 public Object SelectedPane { get {...} set { BaseViewModel var = (value as UserControl).DataContext as BaseViewModel; } } 但我不知道这是不是你的想法。
  • 嗯...我不知道 Telerik 控件,因此您可能需要在 SO 或 Telerik 论坛上询问具体问题。任何使用绑定的东西都可以用代码/事件处理来代替,只是需要做更多的工作。
  • 我知道绑定到具有某些视图特定类类型的属性是不好的,例如 RadPane SelectedPane {}。我知道我应该绑定到具有视图模型(或其基类)类型的属性。所以我在问绑定到 Object SelectedContent {} 是否是一个更好的解决方案(它将视图作为对象返回,但转换为 UserControl 为我们提供了作为视图模型的数据上下文)。它只是不直接,就像拥有 BaseViewModel ActiveTab {}。
猜你喜欢
  • 2013-10-08
  • 2013-09-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-02-17
  • 1970-01-01
  • 2012-09-07
相关资源
最近更新 更多