我可以使用路由命令或路由事件从子视图模型到主视图模型 window 进行通信吗?
Can I communicate from child viewmodels to main window with a routed command or routed event?
我正在构建一个 MVVM WPF 应用程序,其中包含驻留在主 window 中并由其管理的自定义对话框控件。我希望能够从应用程序中的任何位置启动此对话框(例如,从属于某处某个子视图的视图模型)。
我的问题是:我可以使用冒泡的 RoutedCommand 或 RoutedEvent 以某种方式从某些子视图的视图模型中的逻辑获取主 window 并显示对话框,利用元素树和 WPF 的路由系统而不是将事物紧密耦合在一起?例如,我有一个 ViewModelBase,并且希望能够从任何地方调用 ViewModelBase.ShowDialog() 并触发主要 window.
中的对话逻辑
我觉得这可行,但我不太明白。与其他人一样,所有关于如何使用 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.
}
您可以设置一个静态 class,它可以只是一个 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}"/>
我正在构建一个 MVVM WPF 应用程序,其中包含驻留在主 window 中并由其管理的自定义对话框控件。我希望能够从应用程序中的任何位置启动此对话框(例如,从属于某处某个子视图的视图模型)。
我的问题是:我可以使用冒泡的 RoutedCommand 或 RoutedEvent 以某种方式从某些子视图的视图模型中的逻辑获取主 window 并显示对话框,利用元素树和 WPF 的路由系统而不是将事物紧密耦合在一起?例如,我有一个 ViewModelBase,并且希望能够从任何地方调用 ViewModelBase.ShowDialog() 并触发主要 window.
中的对话逻辑我觉得这可行,但我不太明白。与其他人一样,所有关于如何使用 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.
}
您可以设置一个静态 class,它可以只是一个 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}"/>