WPF NotifyIcon

July 29th, 2019

Version 1.0.8 released April 2nd 2016.

This is an implementation of a NotifyIcon (aka system tray icon or taskbar icon) for the WPF platform. It does not just rely on the Windows Forms NotifyIcon component, but is a purely independent control which leverages several features of the WPF framework in order to display rich ToolTips, Popups, context menus, and balloon messages. It can be used directly in code or embedded in any XAML file.

image

Browse/fork/clone on GitHub (includes sample application)
Download library via NuGet

Features at a glance

  • Custom Popups (interactive controls) on mouse clicks.
  • Customized ToolTips (Vista and above) with fallback mechanism for xp/2003.
  • Rich event model including attached events to trigger animations in Popups, ToolTips, and balloon messages. I just love that.
  • Full support for standard Windows balloons, including custom icons.
  • Custom balloons that pop up in the tray area. Go wild with styles and animations 🙂
  • Support for WPF context menus.
  • You can define whether to show Popups on left-, right-, double-clicks etc. The same goes for context menus.
  • Simple data binding for Popups, ToolTips and custom balloons through attached properties and derived data context.
  • Command support for single / double clicks on the tray icon.

Tutorial and Support

      • A comprehensive tutorial that complements the attached sample application can be found on the Code Project:

http://www.codeproject.com/KB/WPF/wpf_notifyicon.aspx

Please post support questions to the CodeProject forum only. Thank you.

Screenshots

The screenshots below were taken from NetDrives and the sample application.

quickaccess

image

image

image

image

XAML Declaration Sample

The sample below shows some of the properties of the control. For a more comprehensive sample, have a look at the sample application that comes with the download.

<Window
  x:Class="Hardcodet.NetDrives.UI.SystemTray.Sample"
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  xmlns:tb="http://www.hardcodet.net/taskbar">

    <tb:TaskbarIcon x:Name="myNotifyIcon"
                    Visibility="Visible"
                    ToolTipText="Fallback ToolTip for Windows xp"
                    IconSource="/Images/TrayIcons/Logo.ico"
                    ContextMenu="{StaticResource TrayMenu}"
                    MenuActivation="LeftOrRightClick"
                    TrayPopup="{StaticResoure TrayStatusPopup}"
                    PopupActivation="DoubleClick"
                    TrayToolTip="{StaticResource TrayToolTip}"
      />

</Window>
  1. Horst
    May 7th, 2009 at 12:06 | #1

    Thank you so much, Philipp! I’m looking forward to getting rid of the Winforms dependency.

  2. May 7th, 2009 at 12:09 | #2

    You’re welcome – happy coding 🙂

  3. Fabian
    May 8th, 2009 at 19:54 | #3

    What are the terms of use. I want it to use for free school-program, is that ok?

  4. May 8th, 2009 at 20:41 | #4

    Fabian,
    This is free software and the license (CodeProject Open License) even permits you to develop closed-source commercial software, so no worries.

  5. Loic Berthollet
    May 10th, 2009 at 21:48 | #5

    Hie,
    Very impressive work !
    Thank’s for sharing it.

    Maybe a problem : in ‘TaskBarIcon.cs’, the 2 call to ‘Popup.CreateRootPopup( )’ throws several binding expressions error in visula studio output window.

    Loic

    • May 10th, 2009 at 23:10 | #6

      Loic,
      Popup.CreateRootPopup tries to create the binding that you saw in the debug window, but this is nothing to worry about – CreateRootPopup just tries to bind to these properties in case the control you want to use for a popup should behave accordingly. For more information, use reflector to have a look at the CreateRootPopup method, and see the MSDN page of CreateRootPopup: http://msdn.microsoft.com/en-us/library/system.windows.controls.primitives.popup.createrootpopup.aspx

      If the debug output annoys you, you can replace the CreateRootPopup call by: popup.Child = TrayPopup;

      Edit: Version 1.0.1 no longer calls CreateRootPopup, so the debugs warning are gone.

      Cheers,
      Philipp

  6. May 11th, 2009 at 11:37 | #7

    This is excellent, I was just looking for a NotifyIcon for WPF.
    Thanks!

  7. nicp
    May 11th, 2009 at 15:04 | #9

    hey Philip, nice work on this – very nice looking little library.

    I’ve had a problem using your trayicon in my MVVM app though. It seems the DataContext is not getting set on the ContextMenu so if I bind a MenuItem’s Command property to my ViewModel the Commands are not getting executed. I’ve fixed this by modding your source code to set the DataContext property of the ContextMenu in the ShowContextMenu – not sure if this is the recommended approach but it’s working for me.

    cheers
    Nic

    • May 11th, 2009 at 16:15 | #10

      I’d say it’s the expected behavior, because the TaskbarIcon is not set as the ContextMenu’s PlacementTarget. I could either use the attached property to give you access to the TaskbarIcon or explicitely assign the DataContext. I’ll think about it and will get back to you.

      Edit: Version 1.0.1 solves this issue – ContextMenu is now a first class citizen when it comes to DataBinding and also gets the TaskbarIcon’s DataContext and ParentTaskbarIcon attached dependency property (see tutorial / data binding samples.

  8. May 11th, 2009 at 17:37 | #11

    Any plans of adding this to Codeplex? It might serve to get it more exposure and contribution. This is definitely something that should be added to the WPF toolkit. Though it probably wouldn’t be since it’s a Windows Desktop only type of control, still something that has been sorely missing when doing wpf apps.

    • May 11th, 2009 at 18:21 | #12

      Jeff,
      I’m currently outlining a CodeProject article for this one – this should give it some more exposure. I’ll think about CodePlex – thanks for the suggestion 🙂

  9. Björn I
    May 15th, 2009 at 17:57 | #13

    This is great stuff!.. thanks 🙂

    • May 15th, 2009 at 17:58 | #14

      Thanks Björn – glad you like the control! And stay tuned – I’m finalizing V 1.0.1 and a set of tutorials on the subject.

  10. May 16th, 2009 at 23:32 | #15

    Oh, this is great. Much better than the standard WinForm icon. It’s no wonder that microsoft will ask you to integrate this in WPF 4 😛

  11. mousou2003
    June 10th, 2009 at 18:28 | #17

    Hi,

    Can you describe a little bit more the need of this namesapace:
    xmlns:tb=”http://www.hardcodet.net/taskbar”>

  12. June 10th, 2009 at 18:47 | #18

    You can compare a namespace with a using statement in C# – it basically tells the XAML parser where to find the declared class. For further information, have a look here:
    http://msdn.microsoft.com/en-us/library/ms747086.aspx

  13. June 26th, 2009 at 16:04 | #19

    Hi. Thanks a lot for this code. It’s great.

    I made a modification to make it work with RoutedCommands. Right now if you assign a RoutedCommand to LeftClickCommand or DoubleClickCommand, the command is not invoked. This is due to the way you are invoking commands in the ‘ExecuteIfEnabled’ extension method and arguably due to a bad implementation of the RoutedCommand ‘CanExecute’ method.

    To make this scenario work, you must add the following method to the ‘TaskbarIcon’ class and replace the 5 calls to ‘ExecuteIfEnabled’ by a call to this new method:

    protected void ExecuteCommandIfEnabled(ICommand command, object commandParameter)
    {
    if (command != null)
    {
    RoutedCommand routedCommand = command as RoutedCommand;
    if (routedCommand == null)
    {
    command.ExecuteIfEnabled(command);
    }
    else
    {
    if (routedCommand.CanExecute(commandParameter, this))
    {
    routedCommand.Execute(commandParameter, this);
    }
    }
    }
    }

    Thanks again.

  14. July 2nd, 2009 at 09:06 | #20

    Rodolfo,

    Thanks for the contribution. This is fixed in 1.0.3 which also provides CommandTarget properties for both commands.

  15. Tony Juricic
    July 12th, 2009 at 03:06 | #21

    Thanks for the code! For interop scenarios (which happens to be my case, i.e. MFC app invoking managed COM object) I would add GuiDispatcher property since in these cases Application.Current will be null. That’s what I did and so far it works just fine within a MFC app.

  16. Tony Juricic
    July 12th, 2009 at 15:13 | #22

    A bit more elegant – adding GuiThreadDispatcher property and then initializing it in constructor like:
    GuiThreadDispatcher = Dispatcher.CurrentDispatcher;
    takes care of possibly null Application object. User is obliged to create icon on UI thread but that is nothing unusual with WPF.

  17. Felix
    July 30th, 2009 at 09:31 | #23

    It seems that it is not possible to host a textbox in a taskbar popup. It will be displayed but I can’t enter text. Pasting text from clipboard is possible though…
    Has anyone experienced the same issue?
    BTW thanks for sharing this knowledge and code…

  18. August 3rd, 2009 at 20:18 | #24

    Hi Philip,

    Looks like an excellent control. I got it up and running pretty easy.

    One question though. Do you know why my input controls (TextBox for example) do not receive focus once I place them on the popup? It appears that a TextBox does work when I add it to the WelcomeBalloon.xaml, which is a custom balloon. If I set the WelcomeBalloon to be the popup, the TextBox is unable to receive focus.

    I’d like to be able to use a TextBox on the PopUp so that people are able to enter their current status which is then immediately updated, like Live Messenger. Hope you can point me in the right direction.

    Thanks!

  19. mike
    August 17th, 2009 at 18:55 | #25

    Hi,

    thanks for the tutorial. but I tried it and I continued to get an error stating that i was missing a assembly reference. I did add xmlns:tb=”http://www.hardcodet.net/taskbar” in the namespace. My code looks identical to the code provided, any suggestions?

    thanks,

    Mike

  20. August 18th, 2009 at 15:31 | #26

    Mike, did you add a reference to the assembly (the DLL in the “References” folder) in your project?

  21. seven
    August 21st, 2009 at 07:22 | #27

    It’s not working in Windows 7 RTM x64, getting invalid menu handle in the CreateMessageWindow() method apart of WindowMessageSink.cs. XP works fine, don’t know about Vista. Can you fix it. Also you need to update your sample took me forever to get it to compile under VS 2010.

  22. August 21st, 2009 at 12:53 | #28

    @seven
    Seven, the project runs just fine on Win7 RC1 x64, at least under VS2008. Haven’t looked at it in VS2010 yet, but given the new VS is beta software, I don’t plan on changing the code for it so far. Of course, if the problem’s still there with .NET 4.0 RTM, I’ll provide an update asap.

  23. Dave Keller
    August 26th, 2009 at 16:18 | #29

    Hi There

    Are there any samples out there where I am ale to get VB.NET samples

  24. August 26th, 2009 at 16:35 | #30

    Dave,

    I’m afraid the sample is only available as a C# project. However – most is XAML anyway, so this shouldn’t make too much of a difference. If you want to convert the code in the sample application, you can run it through a converter, e.g. http://converter.telerik.com/

    And in case you haven’t already, check out the CodeProject tutorial.

  25. August 27th, 2009 at 00:33 | #31

    Hello Philipp,
    This question was also posted on CodeProject by “headarmleg”. I am having the same problem.
    Here is what “headarmleg” wrote

    This is great tool, thanks for posting!

    Only problem I’m having is trying to show a custom balloon containing a listbox. When I display the control it shows the listbox with all of it’s items correctly and the scroll bars work. What I can’t seem to get working is to be able to select items or handle the selection changed event. Anyone know what I’m doing wrong? Thanks in advance!

    I was able to reproduce this in the FancyPopup.xaml sample by adding the following in the grid (covering the textblock in the middle)

    None of the items are selectable.
    Do you have any thoughts on why this is happeing, or what might make it work.
    Thanks
    Kevin

  26. Batiste
    August 28th, 2009 at 14:54 | #32

    @Sander Schutten
    Same problem here, the textbox aren’t able to take input.
    Here’s a sample to reproduce :

    When the textBox is displayed we can’t put text in it.

    nevertheless, good job on that one !

  27. August 28th, 2009 at 15:24 | #33

    I’m on the issue with the disabled TextBox – this can be reproduced with regular Popups as well. I’ll have time to look at it next week and hopefully come up with a workaround.

    Edit: Should be fixed with 1.0.4

  28. Anton Romanov
    September 2nd, 2009 at 14:55 | #34

    @Tony Juricic
    Can you create a sample usage within winforms/win32 application?

  29. Daniel
    September 10th, 2009 at 12:53 | #35

    Hi Philip,

    Thanks for the sharing.
    I found it does work well in windows XP with SP1(VS2008),However, it doesn’t work in windows XP without SP1(VS2008).
    Could you please give some advice about this issue?

  30. September 10th, 2009 at 12:58 | #36

    Daniel,

    I’m afraid I don’t have a machine where SP1 isn’t present, here. SP1 was a major upgrade which I’d recommend to be present anyway. I don’t know exactly what the dependency is, but: Did you try to compile the component alone (without the sample application)?

  31. September 17th, 2009 at 16:37 | #37

    Thanks you!

  32. September 22nd, 2009 at 08:39 | #38

    The issues with Popups and/or ListView controls should be fixed with 1.0.4. Thanks to all for reporting the bug 🙂

  33. Fox
    September 24th, 2009 at 22:07 | #39

    Myabe a bug or maybe not.

    I was trying to use the OS standard popups (ShowBalloonTip) but it didn’t work. The problem was my Icon because its was 48×48, I tried a 16×16 one and it worked… (You can see the 48×48 icon in the tray but the popup didn’t work)

  34. September 24th, 2009 at 23:09 | #40

    @Fox
    I’m pretty sure this is an OS restriction. Thanks for posting the solution!

  35. mbaldini
    September 28th, 2009 at 19:19 | #41

    For some reason the LeftMouseButtonUp events have not been firing for the Context menu items.

    I have tried in xaml and in code to hook to the event, but have not been successful.

    Am I missing something?

  36. October 1st, 2009 at 19:36 | #42

    Thank you so much Mr. Sumi.
    Its realy great job.
    Regards…

  37. October 2nd, 2009 at 10:33 | #43

    @mbaldini
    This event never fires for context menu items – you can easily reproduce this with a regular context menu on a window.

  38. October 5th, 2009 at 14:27 | #44

    Very nice!

    One quick suggestion – your RoutedEventHelper class has special cases for UIElement and ContentElement, but the relevant methods are defined on the IInputElement interface. This would simplify the code and also cover UIElement3D.

    internal static void RaiseEvent(DependencyObject target, RoutedEventArgs args)
    {
    var element = target as IInputElement;
    if (null != element) element.RaiseEvent(args);
    }

  39. Ciantic
    October 6th, 2009 at 09:45 | #45

    To make it more WPFish, Icon should allow URIs like Window Icon property does, e.g.
    This is allowed, thus: should be allowed too.

    I find it highly illogical that such problems are also in Microsoft’s own libraries, Window element takes URI’s just fine, but MenuItem.Icon takes ImageSources, very confusing when same named properties doesn’t eat same stuff.

    Thanks, great work btw!

  40. October 6th, 2009 at 09:46 | #46

    @Ciantic
    I think you are looking for the IconSource property. The NotifyIcon supports both 🙂

  41. Ciantic
    October 6th, 2009 at 09:49 | #47

    @Philipp Sumi
    Oh thats fantastic, (awesome fast reply), though I still think that same named property should eat same kind of stuff. (Maybe some converter could route it to IconSource?)

  42. October 6th, 2009 at 09:55 | #48

    @Ciantic
    A single property won’t do – these are different data types. IconSource is what you use in XAML, while you can use the Icon property to simply assign the icon in code (e.g. if your icon is in a resource file, and that’s also the component’s internal format).

    Have a look at the CodeProject tutorial, it shows both scenarios.

    Happy coding!
    Philipp

  43. Ciantic
    October 6th, 2009 at 12:25 | #49

    Bug nr. 2 (Context menu is wrongly placed when used in two places)

    Here is full details and patch to that also: http://users.jyu.fi/~jaotospe/wpficon_bug2.txt

  44. October 6th, 2009 at 13:27 | #50

    @Ciantic
    This is not a bug, but by design. I had to look into the change log for the reason, though:
    CHG Popups and ContextMenu now store coordinates - otherwise delayed opening may happen elsewhere.

    You can reproduce this by just setting the MenuActivation to LeftClick. If you now left-click the NotfiyIcon and move the mouse away quickly, the context menu will open at the mouse pointer’s location, which is not the desired place. This is because there is no PlacementTarget set for the context menu.

    Still: If you want to reuse the same context menu by the NotifyIcon and other elments on your window, just declare it as a resource, with x:Shared="false". Like this, your NotifyIcon will have an independent menu for itself.

Comment pages
1 2 3 7 452
  1. May 11th, 2009 at 13:45 | #1
  2. May 26th, 2009 at 18:13 | #2
  3. June 1st, 2009 at 00:52 | #3
  4. June 24th, 2009 at 18:37 | #4
  5. August 4th, 2009 at 06:13 | #5
  6. October 18th, 2009 at 11:00 | #6