如何将菜单项命令连接到视图上的自定义命令和方法
本文关键字:命令 自定义 方法 视图 菜单项 连接 | 更新日期: 2023-09-27 18:11:32
我有一个简单的TextBlock上的视图,我添加了一个ContextMenu。我想为MenuItem连接Command来执行View上的一个方法。大半天后,我只找到了一个可行的解决方案,这让我相信我错过了什么。有那么多事情对我来说就是没有意义。
这是我唯一能让它工作的方法。
<TextBlock Text="Test">
<TextBlock.ContextMenu>
<ContextMenu>
<MenuItem Header="Test Me" Command="w:Command.TestMe" />
</ContextMenu>
</TextBlock.ContextMenu>
</TextBlock>
public static class Command
{
public static readonly RoutedUICommand TestMe= new RoutedUICommand("Test Me", "TestMe", typeof(MainWindow));
}
在MainWindow类中:
public MainWindow()
{
CommandBindings.Add(new CommandBinding(Command.EditAlarm, new ExecutedRoutedEventHandler(EditAlarmDetails), new CanExecuteRoutedEventHandler(CanEditAlarm)));
InitializeComponent();
Focus();
}
public void CanTestMe(object sender, CanExecuteRoutedEventArgs e)
{
e.CanExecute = true;
}
public void TestMeDetails(object sender, ExecutedRoutedEventArgs e)
{
TestView view = new TestView();
view.ShowDialog();
}
为什么当我在XAML中声明命令绑定时,我终于让它工作了,但菜单项总是被禁用?
<Window.CommandBindings>
<CommandBinding Command="w:Command.TestMe" Executed="TestMeDetails" CanExecute="CanTestMe" />
</Window.CommandBindings>
为什么我不能只是声明一个RelayCommand和引用,就像我通常会从ViewModel?
public ICommand TestCommand
{
get
{
if (testCommand == null)
testCommand = new RelayCommand(param => TestMeDetails(), param => CanTestMe());
return changeStatusCommand;
}
}
public bool CanTestMe()
{
return true;
}
public void TestMeDetails() { }
为什么routeduiccommand类必须是一个在一个单独的静态类工作,但有一个类型的(MainWindow),而不是自己的静态实例类型的(命令)?肯定有什么我不明白的地方。当然,将一个简单的命令事件连接到一个按钮或元素不会这么复杂吧?
理想情况下 ICommand
应该留在ViewModel中,但如果你想在windows后面的代码中创建它,你也可以实现(不创建RoutedCommand)。
你可以像在ViewModel中那样绑定命令,但在此之前你需要考虑这些情况。
-
ContextMenu不位于它所应用的控件的同一视觉树中。所以,要绑定父窗口,你必须使用
PlacementTarget
。 - 一旦你得到了放置目标,你就可以像在ViewModel中对任何命令一样在后面绑定代码。
下面的代码可以运行:
XAML
<TextBlock Text="Test"
Tag="{Binding RelativeSource={RelativeSource Mode=FindAncestor,
AncestorType=Window}}">
<TextBlock.ContextMenu>
<ContextMenu>
<MenuItem Header="Test Me"
Command="{Binding PlacementTarget.Tag.TestCommand,
RelativeSource={RelativeSource Mode=FindAncestor,
AncestorType=ContextMenu}}"/>
</ContextMenu>
</TextBlock.ContextMenu>
</TextBlock>
注意,我在标签中放置了窗口,并使用PlacementTarget从菜单项中访问。
代码后面
private ICommand testCommand;
public ICommand TestCommand
{
get
{
if (testCommand == null)
testCommand = new RelayCommand(param => TestMeDetails(),
param => CanTestMe());
return testCommand;
}
}
public bool CanTestMe()
{
return true;
}
public void TestMeDetails() { }