【问题标题】:Can I communicate from child viewmodels to main window with a routed command or routed event?我可以使用路由命令或路由事件从子视图模型到主窗口进行通信吗?
【发布时间】:2015-02-25 18:04:50
【问题描述】:

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

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

我觉得这可能会奏效,但我不太明白。和其他人一样,所有关于如何使用 RoutedCommand 来复制粘贴菜单项幸福的文献都让我不知所措。我已经为类似的事情构建了事件聚合器,并且我知道带有消息总线的 MVVM 框架已经存在 - 但如果有自然的方法,我想利用 WPF 内置插件而不是另一种一次性解决方案。

编辑:明确地说,我想避免引入额外的依赖项或框架,例如 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.
}

【问题讨论】:

  • 您是否将绑定到您的命令的模式设置为双向绑定?

标签: wpf mvvm routed-events routed-commands


【解决方案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}"/>

【讨论】:

  • @user1454265 您可以设置一个单例命令来处理从您的孩子ViewModels 冒泡到MainWindow 的所有命令。例如,为每个子视图模型注册命令并将其冒泡
  • @user1454265 我更新了我的答案,它是在没有 IDE 的情况下编写的,所以它主要是伪代码,但这个想法应该存在。如果您有任何问题,请告诉我。
  • 谢谢,我使用这个想法让它工作了(虽然不需要订阅者列表,因为我所有的视图模型都可以从 ViewModelBase 调用命令。)我将在编辑中发布我的工作代码以供参考。跨度>
  • @user1454265 抱歉,哈哈。我确实在 SO 中编写了该代码,因此没有经过测试。
猜你喜欢
  • 1970-01-01
  • 2016-02-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-09-26
  • 2019-05-17
相关资源
最近更新 更多