多窗口WPF应用程序中的命令绑定
我的应用程序可以有多个设计器窗口。每个窗口都由几个用户控件组成,这些控件在RelayCommand的帮助下进行动态通信。我创建了以下类作为指挥基础设施的主干多窗口WPF应用程序中的命令绑定,wpf,mvvm,command,icommand,relaycommand,Wpf,Mvvm,Command,Icommand,Relaycommand,我的应用程序可以有多个设计器窗口。每个窗口都由几个用户控件组成,这些控件在RelayCommand的帮助下进行动态通信。我创建了以下类作为指挥基础设施的主干 public static class Commands { public static readonly RoutedCommand EntityEditRequest = new RoutedCommand(); public static RelayCommand EntityEditorChangeRequest;
public static class Commands
{
public static readonly RoutedCommand EntityEditRequest = new RoutedCommand();
public static RelayCommand EntityEditorChangeRequest;
public static RelayCommand XMLUpdateRequest;
public static RelayCommand SaveRequest;
}
用户控件的每个viewmodel都将在构造函数中执行类似的操作
public XMLEditorViewModel()
{
Commands.Commands.SaveRequest = new RelayCommand(Save_Executed);
Commands.Commands.XMLUpdateRequest = new RelayCommand(UpdateXML);
}
然而,我完全忽略了应用程序可以有多个窗口这一点。打开每个窗口时,将为该特定窗口设置静态命令
例如:
窗口A打开,usercontrols的构造函数设置了RelayCommand,一切正常
窗口B打开了设置RelayCommand的usercontrols的构造函数。窗口A的命令绑定丢失
因此,当我将选项卡更改为窗口A(窗口是选项卡式的)时,没有命令起作用
我需要一些想法,以便在我更改选项卡时,活动窗口始终设置命令。我可以试着把命令放在tab_selection_changed事件中,但不知怎么的,我觉得这看起来很糟糕。有没有合适的方法?非常感谢您的帮助
编辑:
这个问题在读者中有点令人困惑。我没有尝试为一个命令创建多个订阅服务器。在任何给定点,只有一个窗口处于活动状态。此窗口由多个用户控件组成,其中一些控件在命令的帮助下动态加载;但每个命令都由一个视图模型类处理,因此没有多个订阅者。我的问题是,应用程序可以在选项卡中加载多个窗口。在任何给定点,只有一个窗口处于活动状态,但用户可以对不同的选项卡执行操作,并使另一个窗口处于活动状态。当视图模型构造函数分配静态RelayCommands时,当加载每个新窗口时,静态命令被设置为新绑定
窗口打开的窗口视图模型构造函数将静态命令绑定设置为其对象命令处理程序。窗口A处于活动状态。指挥很好
窗口B加载的窗口B视图模型构造函数将静态命令绑定设置为其对象命令处理程序。窗口B处于活动状态。指挥很好
现在,用户选择“窗口A”选项卡以将窗口A设置为活动状态。指挥是行不通的。当然不会,因为命令绑定到windowb命令处理程序
理论上,静态命令可以处理场景,因为在任何给定点,只有一个活动窗口。但是怎么做呢?你为什么决定把它放到静态类中
class XMLEditorViewModel
{
public ICommand SaveRequest { get; private set; }
public XMLEditorViewModel()
{
SaveRequest = new RelayCommand(Save_Executed)?
}
}
全局命令应该是一个或类似的方法(
CompositeCommand
来自Prism)。这将允许多个子项使用该命令注册
public static CompositeCommand SaveCommand = new CompositeCommand();
然后可以在ViewModels中访问该命令,或者在适用的情况下,如
SaveCommand = new DelegateCommand<object>(Save, CanExecuteSave);
GlobalCommands.SaveCommand.RegisterCommand(SaveCommand);
SaveCommand=newdelegateCommand(Save,CanExecuteSave);
globalCommand.SaveCommand.RegisterCommand(SaveCommand);
然后,您可以利用定义哪个窗口
是活动的窗口
,并相应地执行命令
上还有一个MSDN帖子。不要忘记注销该命令以避免内存泄漏。可以在静态类上定义不特定于视图的命令 应在视图模型上定义视图特定的命令, 作为DataContext传递到视图,支持单独的实现 对于具有不同视图模型的不同视图, 或者至少让视图传递一个CommandParameter 可用于标识它们(例如,对视图的引用)或它们的数据上下文 如果命令是静态的,则只注册一次,
可能在视图模型使用的单例上。创建全局可用的命令,创建DelegateCommand或CompositeCommand的实例,并通过静态类公开它 公共静态类GlobalCommands { 公共静态CompositeCommand MyCompositeCommand=新的CompositeCommand(); } 在模块中,将子命令与全局可用命令相关联 globalCommand.MyCompositeCommand.RegisterCommand(command1); globalCommand.MyCompositeCommand.RegisterCommand(command2); 为了提高代码的可测试性,可以使用代理类访问全局可用的命令,并在测试中模拟该代理类 下面的代码示例演示如何将按钮绑定到WPF中的命令
执行我的复合命令像Save这样的命令通常是静态的,因为您不想在创建新实例和Save定义时浪费每个ViewModel。命令的静态方法提供了应用程序的全局方法;这将允许您在相关的位置注册…而不是在使用Save的任何位置创建一个一次性的。@snowbear,因为窗口中有许多用户控件,任何用户控件都可以触发该命令。这并不是说命令将由xmleditorview触发。命令的整个要点是更好地将逻辑与设计分离,使用事件使命令工作是错误的方法。@Danny也许,但这完全不同,我有一个合理的理由这样做。这里的问题是,当有许多选项卡式窗口时,如何使全局命令绑定到活动窗口。@Danny请阅读我编辑的文章。我的问题是如何根据多窗口场景中活动窗口的更改重新绑定静态命令。我的问题是,如果稍微更改设计,则不必重新绑定静态命令。@Aaron多个子绑定不是问题。请阅读我在文章中的编辑。@Jimmy这是为了显示如何设置全局命令;利用IActiveAware接口和复合方法进行指挥。您当前的设计在本质上是极其耦合的;您正在尝试将命令绑定绑定到活动实例。使用IActiveAware策略,因此该命令将根据焦点窗口被激活/停用。我周一要试试这个,我会的