在单击任何按钮之前,上下文菜单中的 WPF 自定义命令将被禁用
我有一个自定义命令,我尝试从上下文菜单执行它们,但它们始终显示为禁用,除非我单击 UI 上的任何按钮(按钮与命令无关)。
单击按钮后,命令开始正确显示(当它们不可用时,它们会被禁用,如果可用则启用)。
编辑:事实证明,不是单击按钮使命令正常工作,而是按钮或其他控件处于焦点(例如,如果我选项卡进入控件,这也启用我的命令)。
这是命令的代码:
<Window.InputBindings>
<KeyBinding Command="{x:Static local:MainWindow.Quit}" Key="Q" Modifiers="Ctrl"/>
<KeyBinding Command="{x:Static local:MainWindow.Disconnect}" Key="D" Modifiers="Ctrl"/>
</Window.InputBindings>
<Window.ContextMenu>
<ContextMenu Opacity="95">
<MenuItem Header="Quit Application Ctrl + Q" Command="{x:Static local:MainWindow.Quit}"/>
<MenuItem Header="Disconnect from the pump Ctrl + D" Command="{x:Static local:MainWindow.Disconnect}"/>
</ContextMenu>
</Window.ContextMenu>
这是命令 CanExecuteMethod:
public static RoutedCommand Quit = new RoutedCommand();
private void QuitCanExecute(object sender, CanExecuteRoutedEventArgs e)
{
e.CanExecute = true;
e.Handled = true;
}
I have a custom command and I try to execute them from the context menu, but they are always displayed as disabled unless I click any button on the UI (buttons do not have anything to do with commands).
After clicking a button, commands start to be displayed correctly (when they are unavailable they get disabled and enabled if available).
Edit: it turns out that it is not the button click which makes command work correctly, but button or other controls in focus (e.g. if I tab into a control this also enables my commands).
Here is the code for commands:
<Window.InputBindings>
<KeyBinding Command="{x:Static local:MainWindow.Quit}" Key="Q" Modifiers="Ctrl"/>
<KeyBinding Command="{x:Static local:MainWindow.Disconnect}" Key="D" Modifiers="Ctrl"/>
</Window.InputBindings>
<Window.ContextMenu>
<ContextMenu Opacity="95">
<MenuItem Header="Quit Application Ctrl + Q" Command="{x:Static local:MainWindow.Quit}"/>
<MenuItem Header="Disconnect from the pump Ctrl + D" Command="{x:Static local:MainWindow.Disconnect}"/>
</ContextMenu>
</Window.ContextMenu>
Here is the commands CanExecuteMethod:
public static RoutedCommand Quit = new RoutedCommand();
private void QuitCanExecute(object sender, CanExecuteRoutedEventArgs e)
{
e.CanExecute = true;
e.Handled = true;
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
此问题是由于上下文菜单位于与窗口及其控件不同的视觉和逻辑树上。
对于仍在寻找此问题答案的人 - 在搜索互联网后,我发现最有效的答案是在需要其命令被其“所有者”听到的 MenuItem 的任何声明中包含以下内容。
通俗地说;如果您希望右键单击的内容能够听到上下文菜单的命令。添加此代码:
示例:
这也适用于模板(我发现很多其他解决方案不支持这一点)。以下是从其他地方摘取的对该声明含义的解释(我对解释事情感到震惊):
老实说,我希望这些信息可以帮助刚接触 WPF 的人解决我这个周末所经历的头痛……尽管它确实教会了我很多东西!
This issue is due to the ContextMenu being on a separate Visual and Logical Tree to that of the Window and its Controls.
For anyone still looking for an answer to this issue - After trawling the internet I have found the most effective answer to be to include the following in any declaration of a MenuItem that needs its commands to be heard by it's "owner".
In layman's terms; if you want the commands of your context menu to be heard by the thing you're right clicking on. Add this code:
Example:
This will also work within Templates (something I found a lot of another solutions not to support). Here is an explanation of the meaning of the statement taken from elsewhere (I'm appalling at explaining things):
I honestly hope that this information saves someone who's new to WPF the headache I've gone through this weekend... though it did teach me a lot!
现在完全不同的轨道:
ContextMenu 作为命令的载体确实有一些特别之处:
菜单不被视为窗口的一部分,因此其行为不像其可视树中的元素那样。
对于此处定义的问题,有不同的解决方案:
http://www.wpftutorial.net/RoulatedCommandsInContextMenu.html
最简单的方法似乎是添加这个到您的 XAML(对于窗口):
Completely different track, now:
there is indeed something special about the ContextMenu as the carrier for commands:
the menu is not regarded as part of the window and therefore does not behave like an element in its visual tree would.
There are different solutions for your problems defined here:
http://www.wpftutorial.net/RoutedCommandsInContextMenu.html
The easiest approach seems to be adding this to your XAML (for the window):
我刚刚在尝试为 AvalonDock 实现自定义上下文菜单时遇到了这个问题。上面建议的解决方案都不适合我。
除了主窗口之外,我还通过在 ContextMenu 类上显式注册命令处理程序来使上下文菜单正常工作。下面的函数是我用来注册命令的助手。
I just ran into this while trying to implement a custom context menu for AvalonDock. None of the solutions suggested above worked for me.
I got the context menu working by explicitly registering my command handlers on the ContextMenu class in addition to the main widow. The function below is a helper I used for command registration.
可能有一些“幕后”更改通常会启用命令,但视图不知道此更改。
人们需要查看命令实现才能给出更精确的提示。
您可以进行任何更改命令启用状态的操作来通知视图,也可以通过 CommandManager.InvalidateRequerySuggested() 手动触发命令刷新,例如在上下文菜单打开时。
WPF ICommand 就是这样工作的;每当视图中的某些内容发生更改(例如,触发 PropertyChanged 事件或单击按钮)时,它们就会重新查询 CanExecute 函数,但如果没有理由,它们就不会重新查询。
There is probably some change "behind the scenes" that would normally enable the commands, but the view is not aware of this change.
One would need to see the Command-implementations to give more precise hints.
You can either make anything that changes your command-enable-state notify the view or manually trigger a command-refresh via
CommandManager.InvalidateRequerySuggested()
, for example when the context-menu opens.WPF ICommands work that way; they requery their
CanExecute
function whenever something in the view changes (e.g. PropertyChanged-event is fired or a button is clicked), but they don't requery if they have no reason to.这是一个已知的错误。如果窗口的主焦点范围内没有焦点元素,则 CanExecute 路由将在 ContextMenu 处停止,因此不会到达 Window 上的 CommandBinding,一种解决方法是将 MenuItem 的 CommandTarget 绑定到主窗口,如下代码所示:
This is a known bug. If there is no focused element in the window's main focus scope, the CanExecute routing will stop at the ContextMenu, so it will not reach to the CommandBinding on the Window, one workaround is to bind MenuItem's CommandTarget to the main window, as following code demonstrates: