3

I'm creating a tray application with WPF (using Hardcodet.NotifyIcon.Wpf NuGet package), which will not display any window at startup. The tray icon has a context menu, but I'm having trouble binding commands to the menu items, since there is nothing that can recieve the commands. I've been trying to bind them to the main application, but it does not seem to work, the CanExecute method is not called, so the menu items are disabled.

My App.xaml resource dictionary looks like this:

<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> 

The code-behind simply binds:

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(); } } 

I have defined my commands in a public static class like this:

public static class Commands { public static readonly RoutedUICommand About = new RoutedUICommand(); public static readonly RoutedUICommand Exit = new RoutedUICommand(); } 

I don't hit breakpoints in any method except the constructor, so I'm guess this approach is invalid somehow. How am I supposed to do this?

2
  • Your issue might be datacontext related. you could just make global commands by have a public static class with public static commands. if it fits your case scenario. Commented Mar 11, 2014 at 10:50
  • @TYY: I'm already doing this, I think. Added my command definitions to the question. Is this what you meant? Commented Mar 11, 2014 at 10:51

2 Answers 2

3

You have to register commands for the correct class. Try to use typeof(Popup) instead of GetType():

CommandManager.RegisterClassCommandBinding(typeof(Popup), aboutBinding); CommandManager.RegisterClassCommandBinding(typeof(Popup), exitBinding); 
Sign up to request clarification or add additional context in comments.

2 Comments

Thanks! This works, but I'm intrigued as to why? I'm not instantiating any Popups. What makes Popup special? I tried various other classes that share some part of the inheritance chain of Popup, but those did not work.
Hardcodet.NotifyIcon.Wpf uses Popups to display context menu in the task bar. It is why commands must be registered for Popup class. By the way, typeof(object) should also work but it seems to be too general.
1

Firstly, it is not desirable that the in ResourceDictionary was any code. His goal store styles and resources for controls rather than the code for them.

Secondly, in this case lost all sense of the commands, as they were created for independent logic between UI and logic of application. Need to define the commands in ViewModel class separately from View, possibly in different namespaces.

Thirdly, use the interface implementation ICommand, for example: RelayCommand or DelegateCommand. I use interface realization of @Josh Smith, but usually it is a matter of taste.

For more information, please see:

WPF Apps With The Model-View-ViewModel Design Pattern

Understanding Routed Commands

ICommand Interface and RelayCommand Class in WPF MVVM

2 Comments

I'm not sure I see how this applies? I don't have any views or view models, as I don't have any windows, as I wrote in the question.
@carlpett: Yes, I understand. I just wrote my thoughts about it, maybe they will be useful to you in the future.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.