Click here to Skip to main content
15,880,967 members
Articles / Desktop Programming / WPF

WPF Toast Notification

Rate me:
Please Sign up or sign in to vote.
3.97/5 (14 votes)
22 Apr 2018MIT5 min read 77.5K   4.2K   32   12
Fancy toast notification for WPF applications easy to use and support MVVM pattern

 

Just download the project demo, restore the missing packages using Nuget and enjoy. Smile | :)

Introduction

Fancy toast notification for WPF applications easy to use and support MVVM pattern. A small notification window with image, title and content displayed at the bottom of the screen. You can use the default implementation or build your own custom notification.

Github

You can check out the project on Github from here, download the source code and the App demo and enjoy. Smile | :)

The demo demonstrates how to use the toast notification to display it with the default implementation or with your own custom implementation.

Nuget

WPF Toast Notification is available on NuGet, you can install it using nuget manager or run the following command in the package manager console.

PM> Install-Package WPFNotification

 

Note:  In the WPF Toast Notification - Deep Dive  article, I explained step by step the code behind the package.

In this article, we will demonstrate

 

Features

  • Simple, lightweight and fancy toast notification with title, content and overridable predefined image displayed at the bottom of the screen.
  • Support MVVM pattern.
  • Adds support for windows 7 or later.
  • Adds support for displaying notification on different screen resolution.
  • Configurable, you can use the default notification configuration or reconfigure it with the following attributes:
    • Display duration
    • Width
    • Height
    • Notification template
    • Notification Flow Direction,That set direction in which new notification window will appear. Available options are:
      • RightBottom (default).
      • LeftBottom.
      • LeftUp.
      • RightUp.
  • Customizable
    • You can implement your own notification
  • Show one notification per time and if there are other notifications, they will be placed in a queue and will be shown when the place is available.
  • Prevent the notification from fading out when hovering on it.
  • Allow to clear all notifications from notification list and notification buffer list

 

Getting Started

Adding the Notification Assembly

  • Open Visual Studio and open an existing WPF application or create a new WPF Application project.
  • Get the latest WPFToastNotification release and unzip its contents to disk or install the WPFNotification package using NuGet.
  • Add an assembly reference to WPFNotification.dll.
  • Modify the App.xaml and add the following resource dictionary reference:
XML
<ResourceDictionary>
  <ResourceDictionary.MergedDictionaries>
   <ResourceDictionary Source="/WPFNotification;component/Assets/NotificationUI.xaml"/>
  </ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
Notet :

If you install WPFNotification package using NuGet. Automatically it will add the assembly reference and modify the App.xaml file for you.

 

Display The Default Toast Notification

Assuming that the notification will be displayed when the user clicks on a button:

  1. If you are using MVVM pattern, you need to do the following steps:
    • Register the INotificationDialogService into your IOC container. I am using SimpleIOC container.
    C#
    SimpleIoc.Default.Register<INotificationDialogService, NotificationDialogService>();
    • Inject INotificationDialogService into your viewModel.
    • Create Notification object with your Title, Message and optional ImgURL (if null, it will display the default predefined image).
    • Finally, call the ShowNotificationWindow method with the notification object.
    C#
    public class MainViewModel : ViewModelBase
    {
            private readonly INotificationDialogService _dailogService;
    
            // inject INotificationDialogservice
    
            public MainViewModel(INotificationDialogService dailogService)
            {
                _dailogService = dailogService;
            }
    
            private RelayCommand _defaultNotification;
    
            /// <summary>
            /// The DefaultNotification command.
            /// Create Notification object and send it to NotificationDialogService 
            /// to display the notification.
            /// </summary>
    
            public RelayCommand DefaultNotification
            {
                get
                {
                    return _defaultNotification
                        ?? (_defaultNotification = new RelayCommand(
                        () =>
                        {
                          // Create the notification object
                            var newNotification = new Notification()
                            {
                                Title = "Machine error",
                                Message = "Error!! Please check your Machine Code and Try Again"
                            };
                          // call the ShowNotificationWindow Method with the notification object
                            _dailogService.ShowNotificationWindow(newNotification);
                        }));
                }
            }
    }
  2. If you are using Code-Behind, you need to do the following steps:
    • Create INotificationDialogService object.
    • Create Notification object with your Title, Message and optional ImgURL (if null, it will display the default predefined image).
    • Finally, call the ShowNotificationWindow method with the notification object.
    C#
    private void Button_Click(object sender, RoutedEventArgs e)
            {
                INotificationDialogService _dailogService = new NotificationDialogService();
                var newNotification = new Notification()
                {
                    Title = "Machine error",
                    Message = "Error!! Please check your Machine Code and Try Again"
                };
                _dailogService.ShowNotificationWindow(newNotification);
            }

Now you should see the notification on your screen like the figure below:

 

Create Custom Notification

Assuming that we will create mail Notification that will be displayed when user clicks on a button.

To create custom notification, we need to do five steps:

Step 1

Create custom notification model, e.g., MailNotification class like below:

C#
public class MailNotification
   {
       public string Title { get; set; }
       public string Sender { get; set; }
       public string Content { get; set; }
   }
Note:

If you want to use the default notification model, but you need to change the notification UI, you should ignore this step and start from step 2.

Step 2

Create the custom Notification UI, e.g. NotificationItem.xaml (user control) and bind it to the MailNotification model like below:

XML
<UserControl x:Class="WPFNotificationDemo.Assets.NotificationItem"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
             mc:Ignorable="d"
             xmlns:self="ASTA.Host.Presentation.Views.Notifications"
             d:DesignHeight="180" d:DesignWidth="320"
             x:Name="NotificationWindow"
             Background="Transparent">
    <UserControl.Triggers>
        <EventTrigger RoutedEvent="Button.Click" SourceName="CloseButton">
            <BeginStoryboard>
                <Storyboard >
                    <DoubleAnimation Storyboard.TargetName="NotificationWindow" 
                    From="1" To="0" 
                    Storyboard.TargetProperty="(Grid.Opacity)" Duration="0:0:0"/>
                </Storyboard>
            </BeginStoryboard>
        </EventTrigger>
    </UserControl.Triggers>
    <UserControl.Style>
        <Style TargetType="UserControl">
            <Style.Triggers>
                <DataTrigger Binding="
                {Binding ElementName=NotificationWindow,Path=Opacity}" Value="0"/>
            </Style.Triggers>
        </Style>
    </UserControl.Style>
    <Grid Background="Transparent">
        <Border Name="border"
                CornerRadius="10"
                Margin="10"
                BorderThickness="1"
                
                BorderBrush="{DynamicResource Accent}">
            <Border.Background>
                <SolidColorBrush Color="{DynamicResource WindowBackgroundColor}" />
            </Border.Background>
            <Border.Resources>
                <Storyboard x:Key="BackgroundAnimation">
                    <ColorAnimation Storyboard.TargetName="WindowBorderBackground" 
                    Storyboard.TargetProperty="Color" 
                    To="{DynamicResource WindowBackgroundColor}" Duration="0:0:.6" />
                </Storyboard>
            </Border.Resources>
            <Border.Effect>
                <DropShadowEffect ShadowDepth="0" Opacity="0.8" BlurRadius="10"/>
            </Border.Effect>
            <Grid Height="160" Width="300" Margin="0">
                <Grid.RowDefinitions>
                    <RowDefinition Height="Auto"></RowDefinition>
                    <RowDefinition Height="*"></RowDefinition>
                </Grid.RowDefinitions>
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="Auto"></ColumnDefinition>
                    <ColumnDefinition Width="*"></ColumnDefinition>
                </Grid.ColumnDefinitions>
                <Image Grid.RowSpan="2" Source="/Resources/Images/newMail.png" 
                Margin="4" Width="80"></Image>
                <TextBlock Text="{Binding Path=Title}" 
                TextOptions.TextRenderingMode="ClearType" 
                TextOptions.TextFormattingMode="Display" 
                Foreground="DimGray" TextAlignment="Center"
                                   FontFamily="Arial" 
                                   FontSize="14" FontWeight="Bold" 
                                   VerticalAlignment="Center"  Margin="4,4,4,2" 
                                   TextWrapping="Wrap" TextTrimming="CharacterEllipsis" 
                                   Grid.ColumnSpan="2" />
                <Button x:Name="CloseButton"
                        Grid.Column="1"
                        HorizontalAlignment="Right"
                        Margin="0,0,27,0"
                        Click="CloseButton_Click"
                        Style="{StaticResource SystemCloseButton}"
                        Width="16"
                        Height="16" >
                    <Button.Content>
                        <Grid Width="10" Height="12" 
                        RenderTransform="1,0,0,1,0,1">
                            <Path Data="M0,0 L8,7 M8,0 L0,7 Z" 
                            Width="8" Height="7" VerticalAlignment="Center" 
                            HorizontalAlignment="Center"
                            Stroke="{Binding Foreground, 
				RelativeSource={RelativeSource Mode=FindAncestor, 
                            AncestorType=Button}}" StrokeThickness="1.5"  />
                        </Grid>
                    </Button.Content>
                </Button>
                <StackPanel Orientation="Vertical" Grid.Row="1" 
                Grid.Column="1" VerticalAlignment="Stretch">
                    <StackPanel Orientation="Horizontal" Margin="5">
                        <TextBlock Text="From :" HorizontalAlignment="Left" 
                        VerticalAlignment="Top" FontWeight="Black" 
                        Foreground="DarkGoldenrod"></TextBlock>
                        <TextBlock Grid.Row="0"
                               Grid.Column="1"
                               Text="{Binding Sender}"
                               TextTrimming="CharacterEllipsis"
                               TextWrapping="Wrap"
                               FontFamily="Arial"
                               VerticalAlignment="Center"
                               Foreground="Black"
                               Margin="5,0,0,0"
                               Width="145"/>
                    </StackPanel>
                    <StackPanel Orientation="Horizontal"  Margin="5">
                        
                        <TextBlock Grid.Row="1"
                               Grid.Column="0" Grid.ColumnSpan="2"
                               Text="{Binding Content}"
                               TextTrimming="CharacterEllipsis"
                               TextWrapping="Wrap"
                               FontFamily="Arial"
                               VerticalAlignment="Center"
                               HorizontalAlignment="Stretch"
                               Foreground="Black"
                               Margin="5,0,0,0"
                               Width="150"/>
                    </StackPanel>
                </StackPanel>
            </Grid>
        </Border>
    </Grid>
</UserControl>

We need to add on click event of the close button in the NotificationItem.xaml.cs, to immediately close the notification window before the display duration elapsed.

C#
private void CloseButton_Click(object sender, RoutedEventArgs e)
        {
            Window parentWindow = Window.GetWindow(this);
            this.Visibility = Visibility.Hidden;
            parentWindow.Close();
        }

Step 3

Create resource dictionary file, e.g. MailNotificationUI.xaml, add dataTemplate to define the presentation of your notification data and you must give it name e.g. x:Key="MailNotificationTemplate", as we will need this name when creating the NotificationConfiguration object.

XML
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                    xmlns:Model="clr-namespace:WPFNotificationDemo.Model"
                    xmlns:NotificationView="clr-namespace:WPFNotificationDemo.Assets">

    <DataTemplate x:Key="MailNotificationTemplate" 
    DataType="{x:Type Model:MailNotification}">
        <NotificationView:NotificationItem/>
    </DataTemplate>

</ResourceDictionary>

Step 4

Modify App.xaml and add the MailNotificationUI.xaml resource dictionary reference:

XML
<Application.Resources>
    <ResourceDictionary>
      <ResourceDictionary.MergedDictionaries>
                <ResourceDictionary Source=
                "/WPFNotification;component/Assets/NotificationUI.xaml" />
                <ResourceDictionary Source=
                "/Assets/MailNotificationUI.xaml" />
            </ResourceDictionary.MergedDictionaries>
      <vm:ViewModelLocator x:Key="Locator" d:IsDataSource="True" />
    </ResourceDictionary>
  </Application.Resources>

Step 5

Display the mail notification:

  1. If you are using MVVM pattern, you need to do the following steps:
    • Register the INotificationDialogService into your IOC container.
    C#
    SimpleIoc.Default.Register<INotificationDialogService, NotificationDialogService>();
    • Inject INotificationDialogService into your viewModel.
    • Create NotificationConfiguration object with TemplateName equal to the name of your dataTemplate, remember what we said in step 3.
    • Finally call the ShowNotificationWindow method with notification object and configuration object.
    C#
    public class MainViewModel : ViewModelBase
    {
            private readonly INotificationDialogService _dailogService;
    
            // inject INotificationDialogservice
    
            public MainViewModel(INotificationDialogService dailogService)
            {
                _dailogService = dailogService;
            }
    
            private RelayCommand _mailNotification;
    
            /// <summary>
            /// The MailNotification command.
            /// Create Notification and NotificationConfiguration objects,
            /// and send them to NotificationDialogService to display the notification.
            /// </summary>
            public RelayCommand MailNotification
            {
                get
                {
                    return _mailNotification
                        ?? (_mailNotification = new RelayCommand(
                        () =>
                        {
                          // create notification object
                            var newNotification = new MailNotification()
                            {
                                Title = "Vacation Request",
                                Sender = "Mohamed Magdy",
                                Content = "I would like to request for vacation 
                                           from 20/12/2015 to 30/12/2015 ............."
                            };
                           // create configuration object
                            var configuration = new NotificationConfiguration(TimeSpan.Zero, null,
                                                null,Constants.MailNotificationTemplateName);
                            // call show method with notification and configuration objects
                            _dailogService.ShowNotificationWindow(newNotification, configuration);
                        }));
                }
            }
    }
    Note:

    To chnage notification flow direction. You have to set NotificationFlowDirection property (default value is RightBottom) in Configuration object and pass it to ShowNotificationWindow method.

    When any property of the configuration object is set to null, it will use the default value except the displayDuration property must be TimeSpan.Zero to use the default value (2 seconds).

    C#
    var configuration = new NotificationConfiguration(TimeSpan.Zero, null, 
                                                      null, Constants.MailNotificationTemplateName, 
                                                      NotificationFlowDirection.LeftUp);
     _dailogService.ShowNotificationWindow(newNotification, configuration);
  2. If you are using Code-Behind, you need to do the following steps:
    • Create INotificationDialogService object.
    • Create MailNotification object.
    • Create NotificationConfiguration object with TemplateName equal to the name of your dataTemplate, remember what we said in step 3..
    • Finally, call the ShowNotificationWindow method with notification object and configuration object.
    C#
    private void Button_Click(object sender, RoutedEventArgs e)
            {
                INotificationDialogService _dailogService = new NotificationDialogService();
    
               var newNotification = new MailNotification()
                   {
                      Title = "Vacation Request",
                      Sender = "Mohamed Magdy",
                      Content = "I would like to request for vacation from 20/12/2015 
                                to 30/12/2015 ............."
                   };
           var configuration = new NotificationConfiguration(TimeSpan.Zero, null,
                                    null, Constants.MailNotificationTemplateName);
           _dailogService.ShowNotificationWindow(newNotification, configuration);
    
            }

Now, you should see the mail notification on your screen like the figure below:

Clear Notifications

In some situations we need to clear all notifications, for example, after closing the application we didn't need  notifications to continue displayed on the screen, So to clear all notifications in the buffer list, You have to call ClearNotifications method in NotificationDialogService class

C#
public class ViewModelLocator {
.
.
.
        public static void Cleanup()
        {
            var notificationService = ServiceLocator.Current.GetInstance<INotificationDialogService>();
            notificationService.ClearNotifications();
            App.Current.Shutdown();
        }
} 

History

  • 24 Jan 2016  original Post
  • 12 Feb 2016 Add a link to the WPFToastNotification - A Deep Dive article.
  • 28 Jun 2016 Add new features :
    • Adds support for windows 7 or later
    • Adds support for displaying notification on different screen resolutions
    • Add notification Flow Direction
    • Allow Remove All notifications in the buffer list
       

License

This article, along with any associated source code and files, is licensed under The MIT License


Written By
Software Developer (Senior)
Egypt Egypt
Senior software engineer with experience in Microsoft .net development stack. Having a good knowledge of team- management, solution architecture, and agile environment. I have a great passion for learning new frameworks, tools, and technologies And I do blogging sharing technical articles.

Comments and Discussions

 
QuestionIs this able to show under tablet mode of windows 10? Pin
vannes12-Nov-17 19:20
vannes12-Nov-17 19:20 
GeneralMy vote of 1 Pin
Jacob Himes28-Jun-16 22:06
professionalJacob Himes28-Jun-16 22:06 
GeneralRe: My vote of 1 Pin
Muhammad Magdi29-Jun-16 0:56
Muhammad Magdi29-Jun-16 0:56 
GeneralRe: My vote of 1 Pin
Jacob Himes29-Jun-16 7:39
professionalJacob Himes29-Jun-16 7:39 
GeneralRe: My vote of 1 Pin
Muhammad Magdi30-Jun-16 4:33
Muhammad Magdi30-Jun-16 4:33 
QuestionNow that all the dust has settled Pin
Member 105584939-Feb-16 11:59
Member 105584939-Feb-16 11:59 
AnswerRe: Now that all the dust has settled Pin
Muhammad Magdi9-Feb-16 12:34
Muhammad Magdi9-Feb-16 12:34 
BugTells me nothing about how your code was written. Pin
Pete O'Hanlon25-Jan-16 2:14
mvePete O'Hanlon25-Jan-16 2:14 
GeneralRe: Tells me nothing about how your code was written. Pin
Muhammad Magdi25-Jan-16 13:17
Muhammad Magdi25-Jan-16 13:17 
GeneralRe: Tells me nothing about how your code was written. Pin
Pete O'Hanlon25-Jan-16 21:36
mvePete O'Hanlon25-Jan-16 21:36 
GeneralRe: Tells me nothing about how your code was written. Pin
Muhammad Magdi30-Jan-16 6:37
Muhammad Magdi30-Jan-16 6:37 
GeneralRe: Tells me nothing about how your code was written. Pin
Muhammad Magdi12-Feb-16 23:12
Muhammad Magdi12-Feb-16 23:12 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.