Skip to content

nullsoftware/TrayIcon

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

116 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Tray Icon

Library that allows use Tray Icon in WPF Application. Ported from Windows Forms. Has wrapper for WPF ContexMenu (which converts it to Windows Forms ContextMenu). This is needed for good performance, and compatibility. This library targets all MVVM requirements:

  • it has bindable properties
  • it has interface with notify methods

Getting started.

Use one of the follwing methods to install and use this library:

  • Package Manager:

    PM> Install-Package TrayIcon
  • .NET CLI:

    > dotnet add package TrayIcon

First you need to include namespace to your code or markup.

For XAML it can look like:

<Window xmlns:icon="https://github.com/nullsoftware/TrayIcon" />

And for C#:

using NullSoftware.ToolKit;

Then you can place tray icon inside your window, or keep it in variable/property.

For XAML:

<icon:TrayIconHandlers.TrayIcons>
    <icon:TrayIcon Title="My Application"
                   IconSource="MainIcon.ico"
                   ClickCommand="{Binding ExampleCommand}"
                   NotificationServiceMemberPath="NotificationService"/>
</icon:TrayIconHandlers.TrayIcons>

For C#:

TrayIcon myTrayIcon = new TrayIcon() 
{ 
    Title = "My Application",
    IconSource = new BitmapImage(new Uri("pack://application:,,,/MainIcon.ico")),
    ClickCommand = new RelayCommand(ExampleAction)
};

To show balloon you need to call Notify method:

INotificationService notifyService = myTrayIcon;
notifyService.Notify("Greetings", "Hello World!", NotificationType.Information);

Note: INotificationService can be obtained from XAML by using NotificationServiceMemberPath. It injects INotificationService to specified DataContext property.

Backward compatibility

To support latest .NET versions was added ContextMenuVariation property to TrayIcon.
It allows to switch beetwen System.Windows.Forms.ContextMenu or System.Windows.Forms.ContextMenuStrip.
Warning: .NET Core 3.1 and later versions don't support System.Windows.Forms.ContextMenu. See more at the documentation page.

Dynamic context menu items

Any MenuItem (or the root ContextMenu) can have its children built from an ObservableCollection<MenuItem> bound through ItemsSource. Adds, removes, replaces, moves and Clear() (Reset) are forwarded to the underlying tray menu — no need to rebuild the menu manually.

XAML:

<MenuItem Header="Recent Files" ItemsSource="{Binding RecentFiles}"/>

ViewModel:

public ObservableCollection<MenuItem> RecentFiles { get; } = new ObservableCollection<MenuItem>();

private void RegisterRecent(string path)
{
    RecentFiles.Add(new MenuItem
    {
        Header = path,
        Command = new RelayCommand(() => Process.Start(path)),
    });
}

The items in the bound collection must be System.Windows.Controls.MenuItem (or Separator) instances. Direct mutation of MenuItem.Items from code-behind is also supported.

Menu item icons

WPF MenuItem.Icon is forwarded to ToolStripMenuItem.Image automatically. Both static and bound icons are supported, and changes update live.

<MenuItem Header="Open">
    <MenuItem.Icon>
        <Image Source="open.png"/>
    </MenuItem.Icon>
</MenuItem>

Accepted Icon values: a BitmapSource, an Image element with any ImageSource (the typical XAML form above), or any other ImageSource such as DrawingImage — non-bitmap sources are rendered to a 16×16 PNG.

Warning: icons are only rendered when ContextMenuVariation is ContextMenuStrip (the default on .NET Core 3.0+). The legacy System.Windows.Forms.MenuItem used by ContextMenuVariation.ContextMenu has no icon property.

Full Example

<Window x:Class="TrayIcon.Example.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:TrayIcon.Example"
        xmlns:vm="clr-namespace:TrayIcon.Example.ViewModels"
        xmlns:icon="https://github.com/nullsoftware/TrayIcon"
        mc:Ignorable="d"
        Title="MainWindow" 
        Height="450" Width="800"
        Icon="MainIcon.ico">
    <Window.DataContext>
        <vm:MainViewModel/>
    </Window.DataContext>

    <!--Here you can place your icons-->
    <icon:TrayIconHandlers.TrayIcons>
        <icon:TrayIcon Title="My Application"
                       IconSource="MainIcon.ico"
                       DoubleClickCommand="{Binding MinimazeCommand}"
                       NotificationServiceMemberPath="NotificationService">
            <icon:TrayIcon.ContextMenu>
                <!--This context menu will be converted to System.Windows.Forms.ContextMenu-->
                <ContextMenu>
                    <MenuItem Header="Notify" Command="{Binding SayHelloCommand}" icon:TrayIcon.IsDefault="True"/>
                    <Separator/>
                    <MenuItem Header="_Silent Mode" IsCheckable="True" IsChecked="{Binding IsSilentModeEnabled, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>
                    <Separator/>
                    <MenuItem Header="E_xit" Command="{Binding CloseCommand}"/>
                </ContextMenu>
            </icon:TrayIcon.ContextMenu>
        </icon:TrayIcon>
    </icon:TrayIconHandlers.TrayIcons>

    <Grid>
        <StackPanel VerticalAlignment="Top"
                    HorizontalAlignment="Left"
                    Margin="10, 20"
                    Orientation="Horizontal">
            <CheckBox VerticalAlignment="Center"
                      IsChecked="{Binding IsSilentModeEnabled, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
                      Content="Silent Mode"/>
            <Button Margin="20, 0, 0, 0"
                    Padding="10, 3"
                    MinWidth="86"
                    Command="{Binding SayHelloCommand}"
                    Content="Notify"/>
        </StackPanel>
    </Grid>
</Window>

ViewModel:

using System;
using System.Windows.Input;
using NullSoftware.ToolKit;
using PropertyChanged;

public class MainViewModel : ObservableObject
{
    public bool IsSilentModeEnabled { get; set; }

    [DoNotNotify]
    public ICommand MinimazeCommand { get; }

    [DoNotNotify]
    public ICommand SayHelloCommand { get; }

    [DoNotNotify]
    public ICommand CloseCommand { get; }
    
    [DoNotNotify]
    private INotificationService NotificationService { get; set; }

    public MainViewModel()
    {
        MinimazeCommand = new RelayCommand(() => App.Current.MainWindow.WindowState = System.Windows.WindowState.Minimized);
        SayHelloCommand = new RelayCommand(() => NotificationService.Notify("Greetings", "Hello World!"));
        CloseCommand = new RelayCommand(App.Current.MainWindow.Close);
    }
}

Note: in ViewModel was used PropertyChanged.Fody plugin, to simplify usage of INotifyPropertyChanged.

Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

License

This project is licensed under the MIT License - see the LICENSE file for details.

Credits

Developed by Null Software

Repository

https://github.com/nullsoftware/TrayIcon

About

Tray Icon for WPF Application. Has wrapper for WPF ContexMenu.

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages