在没有窗口的WPF应用程序中处理命令

本文关键字:应用程序 处理 命令 WPF 窗口 | 更新日期: 2023-09-27 17:49:24

我正在用WPF创建一个托盘应用程序(使用Hardcodet.NotifyIcon.Wpf NuGet包),它在启动时不会显示任何窗口。托盘图标有一个上下文菜单,但是我在将命令绑定到菜单项时遇到了麻烦,因为没有任何东西可以接收命令。我一直试图将它们绑定到主应用程序,但它似乎不起作用,没有调用CanExecute方法,因此菜单项被禁用。

我的App.xaml资源字典是这样的:

<ResourceDictionary>
    <ContextMenu x:Key="TrayMenu">
        <MenuItem Header="{x:Static res:AppResources.ContextMenu_AboutLabel}" Command="local:Commands.About" />
        <Separator />
        <MenuItem Header="{x:Static res:AppResources.ContextMenu_ExitLabel}" Command="local:Commands.Exit" /> 
    </ContextMenu>
    <tb:TaskbarIcon x:Key="TaskbarIcon"
        ContextMenu="{StaticResource TrayMenu}"
        IconSource="Application.ico" />
</ResourceDictionary>

后面的代码只是绑定:

public partial class App
{
    public App()
    {
        InitializeComponent();
        var aboutBinding = new CommandBinding(Commands.About, AboutExecuted, CommandCanExecute);
        var exitBinding = new CommandBinding(Commands.Exit, ExitExecuted, CommandCanExecute);
        CommandManager.RegisterClassCommandBinding(GetType(), aboutBinding);
        CommandManager.RegisterClassCommandBinding(GetType(), exitBinding);
    }
    private void CommandCanExecute(object sender, CanExecuteRoutedEventArgs e)
    {
        e.CanExecute = true;
    }
    private void AboutExecuted(object sender, ExecutedRoutedEventArgs e)
    {
        Console.WriteLine("About");
    }
    private void ExitExecuted(object sender, ExecutedRoutedEventArgs e)
    {
        Console.WriteLine("Exit");
        Shutdown();
    }
}
我在一个公共静态类中定义了我的命令,像这样:
public static class Commands
{
    public static readonly RoutedUICommand About = new RoutedUICommand();
    public static readonly RoutedUICommand Exit = new RoutedUICommand();
}

除了构造函数之外,我没有在任何方法中遇到断点,所以我猜这种方法在某种程度上是无效的。我该怎么做?

在没有窗口的WPF应用程序中处理命令

您必须为正确的类注册命令。尝试使用typeof(Popup)而不是GetType():

CommandManager.RegisterClassCommandBinding(typeof(Popup), aboutBinding);
CommandManager.RegisterClassCommandBinding(typeof(Popup), exitBinding);

首先,不希望ResourceDictionary中的代码是任何代码。他的目标是存储控件的样式和资源,而不是控件的代码。

其次,在这种情况下,命令失去了所有意义,因为它们是为UI和应用程序逻辑之间的独立逻辑创建的。需要将ViewModel类中的命令与View分开定义,可能在不同的命名空间中。

第三,使用接口实现ICommand,例如:RelayCommandDelegateCommand。我使用@Josh Smith的接口实现,但通常这是一个品味问题。

更多信息请参见:

WPF Apps With The Model-View-ViewModel Design Pattern

Understanding Routed Commands

ICommand Interface and RelayCommand Class in WPF MVVM