我可以使用路由命令或路由事件从子视图模型传递到主窗口吗?

时间:2015-02-25 18:04:50

标签: wpf mvvm routed-events routed-commands

我正在使用自定义对话框控件构建MVVM WPF应用程序,该控件驻留在主窗口中并由主窗口管理。我希望能够从应用程序的任何位置启动此对话框(例如,从属于某个子视图的视图模型)。

我的问题是:我可以以某种方式使用冒泡的RoutedCommand或RoutedEvent从一些子视图的viewmodel中的逻辑到主窗口并显示对话框,利用元素树和WPF的路由系统而不是将事物紧密耦合在一起?例如,我有一个ViewModelBase,并且希望能够从任何地方调用ViewModelBase.ShowDialog()并在主窗口中触发对话逻辑。

我觉得这可行,但我并没有看到它。与其他人一样,关于如何使用Routed命令的所有文献都是我复制粘贴菜单项幸福的方式让我感到茫然。我已经为类似的东西构建了事件聚合器,我知道有消息总线的MVVM框架就在那里 - 但我想利用WPF内置函数而不是另一种一次性解决方案,如果有一种自然的方法的话。 / p>

编辑:要明确,我想避免引入额外的依赖或框架,如Prism。

编辑2:使用以下III的答案中的想法使其工作。这是我用来连线的确切方法:

Commands.cs:提供静态单例命令对象。

// Static class exposing singleton RoutedCommand objects.
public static class Commands
{
    public static readonly ICommand ShowDialog = new RoutedCommand();
}

MainWindow.xaml:通过Window.CommandBindings将其连接到事件处理程序。

<Window xmlns:common="(namespace containing static Commands class)">
    <Window.CommandBindings>
        <CommandBinding Command="{x:Static common:Commands.ShowDialog}" Executed="ShowDialog_Executed" />
    </Window.CommandBindings>
</Window>

MainWindow.xaml.cs

public void ShowDialog_Executed(object sender, System.Windows.Input.ExecutedRoutedEventArgs e) 
{ 
    // handle command
}

ViewModelBase.cs:代表调用者启动RoutedCommand的代码。

protected void ShowDialog()
{
    Commands.ShowDialog.Execute(...); // Can pass dialog text through here.
}

1 个答案:

答案 0 :(得分:1)

您可以设置一个只能是Action的静态类,并处理任何订阅者的注册。订阅该命令的任何人都可以调用该操作。

这个想法是这样的......

public static class CommandManager
{
   List<ViewModel> _subscribers;

   static CommandManager()
   {
     _subscribers = new List<ViewModel>();
     ShowDialogCommand = new Action(() => window.ShowDialog()); // or do whatever you want with your child view models.
   }

   public ICommand ShowDialogCommand { get; private set; }

   public void Register(ViewModel viewModel)
   {
     _subscribers.Add(command);
   }

}

<强> ChildViewModel

public class ChildViewModel
{
   public ChildViewModel()
   { 
      CommandManager.Register(this);
   }
}

查看

<Button Command="{x:Static CommandManager.ShowDialogCommand}"/>