【问题标题】:Handling commands in WPF application without window在没有窗口的 WPF 应用程序中处理命令
【发布时间】:2014-03-11 10:11:47
【问题描述】:

我正在使用 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();
}

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

【问题讨论】:

  • 您的问题可能与数据上下文相关。您可以通过使用带有公共静态命令的公共静态类来创建全局命令。如果它适合您的情况。
  • @TYY:我想我已经这样做了。将我的命令定义添加到问题中。这是你的意思吗?

标签: c# wpf xaml


【解决方案1】:

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

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

【讨论】:

  • 谢谢!这行得通,但我很好奇为什么?我没有实例化任何Popups。 Popup 有什么特别之处?我尝试了各种其他类,它们共享Popup 的继承链的某些部分,但这些都不起作用。
  • Hardcodet.NotifyIcon.Wpf 使用 Popups 在任务栏中显示上下文菜单。这就是为什么必须为 Popup 类注册命令的原因。顺便说一句,typeof(object) 应该也可以,但是好像太笼统了。
  • 我明白了,那是有道理的。谢谢!
【解决方案2】:

首先,不希望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

【讨论】:

  • 我不确定我明白这如何适用?正如我在问题中所写,我没有任何视图或视图模型,因为我没有任何窗口。
  • @carlpett:是的,我明白了。我只是写了我的想法,也许它们将来会对你有用。
猜你喜欢
  • 1970-01-01
  • 2018-09-03
  • 2014-05-29
  • 1970-01-01
  • 2011-03-24
  • 2011-11-14
  • 2016-10-06
  • 1970-01-01
  • 2014-02-09
相关资源
最近更新 更多