This project has moved. For the latest updates, please go here.

NotifyIcon weaknesses ?

Dec 18, 2008 at 11:33 AM
Hi,

Thank you for making this very nice library, i appreciate it very much.

I'd like to point out an issue (maybe a bug ?) regarding NotifyIcon. When i hide the Window in which NotifyIcon is instanciated, the Icon is also hidden, but isnt it a common usage to have a NotifyIcon to be waiting for input while we hide a form ?

It's true that i might be doing it the wrong way too, but i simply had integrated the NotifyIcon as part of my main window XAML, and that window is meant to be hidden and awaiting for commands from NotifyIcon. My solution has been to create a frameless, transparent window size 1,1 and located at -1, -1 for it to be out of the visible area.

I'm having another issue too. I've put a ContextMenu on the NotifyIcon and Events are being called as expected but, i havent found a way to make RoutedCommand or RoutedUICommand working with the ContextMenu on the NotifyIcon. And i've tried many variants of setting it up. Maybe i need so control to grab some kind of focus on the tiny frame i created for the NotifyIcon ?

I could provide a sample if required.

Coordinator
Dec 18, 2008 at 4:19 PM
Hi,

Yes, it is a bug, of sorts. The icon will be displayed in either of these two conditions:
  • The Visibility is set to Hidden (a bit confusing...).
  • The Visibility property is set to Visible (the default) and the IsVisible is set to true. IsVisible is a read-only property, set by WPF when a control is visible in the UI. I didn't realize that hiding the window will set it to false, which is what causes your problem.
So, you can set the Visibility to Hidden when loading your Window/Page/UserControl and set to to Collapsed on unload. This should get you the result you wanted.

As for ContextMenu and routed commands, please le me see the code you're using. It should work.

Aelij.
Dec 19, 2008 at 11:58 AM
hi aelij

Thank you for the quick reply.

Could you be more specific regarding the Visibility properties ? When u say Visibility is set to hidden, do you mean the form or the NotifyIcon ?

Here's my original scenario:

1 WPF Application with 1 Form
The form has some sort of management interface and helps build a list of string/int pairs
A NotifyIcon is added to the form with a ContextMenu
Each pair eventually becomes a menu entry a level 2 of the context menu (in a sub menu)
ContextMenu has 'Open' (unhide the form), 'Close' (quit application), 'Configurations' (Submenu for pairs) and 2 entries each displaying the current state of services we created here. My goal was to have each service menu entry allow us to start/stop the service. And that's where i used commands. CanExecuteCommand was used for the enabled/disabled state of the menu entry, and ExecuteCommand would actually start or stop the service based on current service state.

This seems like a pretty standard scenario to me.

Here's how the app is set so far:
Main Form with management stuff in it, show's a second form of 1x1 pixel at location -1, -1. This second form has the NotifyIcon and it is never hidden. Only thing that i can see that could prevent commands from working is the fact that the form contains nothing apart from the notifyicon. So maybe that could explain commands failing. I've even tried using CommandTarget on the ContextMenu entries but my methods for CanExecute and Executed never get called.

I'll work on a simplified app to provide to you so you can see the problem, just give me a day or 2.

Thank you.





Coordinator
Dec 21, 2008 at 2:13 PM
Hi,

I meant the NotifyIcon's Visibility property. I'm sort of piggybacking it to get what I want (that's why I have an awkward iterpretation of the Hidden mode).

How are you binding to the commands? Show me the code.

Aelij.
Dec 22, 2008 at 12:47 PM
Since i dont know how to attach files, i'll paste the important bits:

Namespace for my commands:

xmlns:c="clr-namespace:DAgent.Controls"

 

 

 

Command Bindings are defined in Xaml at window level (also tried at NotifyIcon level):

 

<Window.CommandBindings

 

 

 

<CommandBinding Command="c:ServiceCommands.StartDispatcher" CanExecute="OnCanStartDispatcher" Executed="OnStartDispatcher" />

 

 

 

<CommandBinding Command="c:ServiceCommands.StopDispatcher" CanExecute="OnCanStopDispatcher" Executed="OnStopDispatcher" />

 

 

 <

CommandBinding Command="c:ServiceCommands.StartMessenger" CanExecute="OnCanStartMessenger" Executed="OnStartMessenger" />

 

 

 

<CommandBinding Command="c:ServiceCommands.StopMessenger" CanExecute="OnCanStartMessenger" Executed="OnStartMessenger" />

 

 

 

</Window.CommandBindings>

 

 

 

Here is my defined NotifyIcon, also tried context menu in Window Resources :

</Window.Resources>

 

 

<Grid>

 

 

<awc:NotifyIcon x:Name="appTrayIcon" Visibility="Visible" Icon="pack://application:,,,/amor.ico" Text="Iconize" DoubleClick="onShowApp">

 

 

<awc:NotifyIcon.ContextMenu>

 

 

<ContextMenu

 

 

Placement="MousePoint" Opened="OnMenuOpened" >

 

 

<MenuItem Header="Open" Click="onShowApp"/>

 

 

<Separator/>

 

 

<!--<MenuItem Header="Configurations"/>-->

 

 

<MenuItem Header="Configurations" ItemsSource="{Binding Source={StaticResource cvs}}"

 

 

ItemContainerStyle="{StaticResource ItemStyle}" Click="OnConfig_Selected"/>

 

 

<Separator/>

 

 

<MenuItem Header="Start Dispatcher" Command="{x:Static c:ServiceCommands.StartDispatcher}"/>

 

 

<MenuItem Header="Stop Dispatcher" Command="{x:Static c:ServiceCommands.StopDispatcher}"/>

 

 

<MenuItem Header="Start Messenger" Command="{x:Static c:ServiceCommands.StartMessenger}"/>

 

 

<MenuItem Header="Stop Messenger" Command="{x:Static c:ServiceCommands.StopMessenger}"/>

 

 

<Separator/>

 

 

<MenuItem Header="Close" Click="Menu_Close"/>

 

 

</ContextMenu>

 

 

</awc:NotifyIcon.ContextMenu>

 

 

</awc:NotifyIcon>

 

 

</Grid>

 

</

Window>


And Finally, my ServiceCommands class

 

using

System.Windows.Input;

 

 

 

using

System.Windows.Threading;

 

 

 

namespace

DAgent.Controls

 

{

 

public static class ServiceCommands

 

 

 

{

 

private static Dispatcher _dispatcher;

 

 

private static RoutedUICommand _stopDispatcher;

 

 

static ServiceCommands()

 

{

StartDispatcher =

new RoutedCommand("StartDispatcher", typeof(ServiceCommands));

 

StartMessenger =

new RoutedCommand("StartMessenger", typeof(ServiceCommands));

 

_stopDispatcher =

new RoutedUICommand("StopDispatcher", "StopDispatcher", typeof(ServiceCommands));

 

StopMessenger =

new RoutedCommand("StopMessenger", typeof(ServiceCommands));

 

_dispatcher =

Dispatcher.CurrentDispatcher;

 

}

 

public static RoutedCommand StartDispatcher { get; private set; }

 

 

public static RoutedUICommand StopDispatcher { get { return _stopDispatcher; } }

 

 

public static RoutedCommand StartMessenger { get; private set; }

 

 

public static RoutedCommand StopMessenger { get; private set; }

 

}

}

 

I'm pretty sure you can foresee the rest of the code, but if you tell me how to submit a file, i'll paste a full project.

Coordinator
Dec 22, 2008 at 6:54 PM
The problem you're having is not related to the NotifyIcon. All Popups in WPF (which includes ContextMenus and ToolTips) are actually top level windows, and thus are not part of the visual tree of the Window that opened them. Routed commands, which are based on routed events, prepagate through the visual tree, and so that is why your commands are not working.

What you should do is perform the command bindings at the ContextMenu level. You can also do this globally for all context menus by using the CommandManager.RegisterClassCommandBinding() method, and passing either Popup or ContextMenu in the type parameter.
Feb 19, 2009 at 12:09 AM
Edited Feb 21, 2009 at 12:11 AM
If you are still having the problem with the commands not routing correctly I think I have a solution.  Add the following lines to the window's constructor.

SetValue(FocusManager.FocusedElementProperty, this);

I recently wrote a blog post about this issue explaining why it happens and why the work around works.  You can find the blog post here: http://cebla5.spaces.live.com/blog/cns!1B8262ED00250003!206.entry

Cheers,

Caleb

Feb 19, 2009 at 12:52 PM
Thank you Caled,

Even thought i don't have time to check your solution right away, i intend to try it in the coming weeks.

Your reply is very appreciated.
May 19, 2009 at 11:10 AM

Hello , 

Is there an update to that Visibilty issue with tray Icon ( which gets Hidden if the owner window is hidden as well ) ???

Thanks

Tomer

Coordinator
May 19, 2009 at 1:53 PM

Hi Tomer,

 

As I said, setting the NotifyIcon's Visibility property to Hidden will ensure it always appears, regardless of the state of its container. To hide it, set the property to Collapsed.

 

Aelij.