Toast Notifications with C#, WPF & MVVM
Published: 2023-12-01 11:51:10

Have you noticed, desktop [notifications](https://www.pubnub.com/use-case/alerts-and-push-notifications/) have become a necessary feature in realtime, [event-driven](https://www.pubnub.com/guides/event-driven-architecture/) apps. Web services need to alert users of back-end signals, or messages from other users, as they happen.

If you’re a software engineer or full-stack software developer looking to build a Windows Desktop application using **C#** and **WPF**, **Windows Forms**, or **UWP**, this guide will walk you through building the **front-end and back-end code** for desktop push notifications with the **MVVM design pattern**.

The star player here is **PubNub’s** [**real-time messaging API**](https://www.pubnub.com/docs/channels/overview), which allows clients or servers to fire real-time signals to any number of devices, web apps, and mobile apps, from anywhere in the world.

**Overview of programming languages needed for toast notifications**
--------------------------------------------------------------------

For this tutorial, we'll be using a variety of coding and algorithm languages. To start, we’ll give a brief definition of those programmer languages and then we’ll dive into the workflow process.

**What is WPF?**
----------------

The code example that we are going to run through together is written using [Windows Presentation Foundation](https://docs.microsoft.com/en-us/dotnet/desktop/wpf/getting-started/introduction-to-wpf-in-vs?view=netframeworkdesktop-4.8) or WPF. For the past decade, WPF has been a best-choice subsystem for developing Windows Desktop web apps with **C# and the .NET Framework**. It resembles Windows Forms with its employment of [XAML](https://docs.microsoft.com/en-us/dotnet/desktop/wpf/fundamentals/xaml?view=netdesktop-5.0) for user interface development and C# [Code Behinds](https://docs.microsoft.com/en-us/dotnet/desktop/wpf/advanced/code-behind-and-xaml-in-wpf?view=netframeworkdesktop-4.8) for every view.

**Quick Tip:**

In this tutorial, we are going to keep as much code as we can outside of the Code Behind because we will be using the MVVM pattern. For this reason, code that would normally appear in the Code Behind classes **will instead go in ViewModel classes**.

**What is MVVM Architecture?**
------------------------------

**Model-View-ViewModel** or MVVM is a design pattern for **separation** of UI development and back-end development in a user-facing application. There are **three components** that make up the pattern.

### What are the components of WPFApps?

For WPFapps, these components are:

-   Views – [XAML and CodeBehinds](https://docs.microsoft.com/en-us/dotnet/desktop/wpf/advanced/code-behind-and-xaml-in-wpf?view=netframeworkdesktop-4.8)
    
-   ViewModels – C# code for state management and controlling data that moves between Model and View.
    
-   Models – C# classes, Data Storage, Business logic.
    

![](https://images.ctfassets.net/3prze68gbwl1/655JWYGQsi4tlNkqAhlEYq/197b20ffa25e393fc71d3959804c5d13/pubnub-mvvm-diagram.png)

**C# Desktop Notifications**
----------------------------

A Windows Desktop solution for OS aware notifications is the **Toast Notification** class. Toast notifications are integrated into the Windows UI Notification class.

### What is a Toast notification?

For this example, we’ll be using a Toast notification. A Toast notification is a small popup that is programmed to appear and expire automatically. It is usually unobtrusive and doesn’t require any action from the user. It also won’t halt user activity.

This type of automated push notification is ideal for desktop popups. However, the support for Toast with WPF is not abundant.

#### **Toast notification pro tip:**

The workaround for this scenario is to build your own toast desktop notification user interface so the WPFapp can include notifications. A notification like this can be **triggered at any time** using a conventional C# event in the ViewModel code.

![](https://images.ctfassets.net/3prze68gbwl1/5xBfgEWMPTg4WpQKODQXXq/080ec85b78673760b19f4091be8f608d/pubnub-wpf-notification.png)

The example we are going to build together is a WPFapp with C# notification.

There will be **one parent window** with a single button. Clicking the button will trigger a PubNub [publish](https://www.pubnub.com/docs/sdks/c-sharp/) of **JSON data** to the network. The application will also **subscribe** to PubNub using the **same channel and API keys** as the publish code (free [PubNubAPI keys](https://dashboard.pubnub.com/signup)).

The PubNub subscribe code will trigger the **C# event** that creates the popup push notification on the Desktop, whenever a new message is published. The latency for PubNub messages is **generally 80 to 100 milliseconds**, regardless of publisher and subscriber distance.

![](https://images.ctfassets.net/3prze68gbwl1/3867ZSWtcQs2csl35ZvUzr/5b32af712a7a3656089dd5d837f4ad74/pubnub-desktop-notification.png)

PubNub has more than **70 client** [**SDKs**](https://www.pubnub.com/docs/sdks) so any internet-capable device can be interchanged into this diagram.

WPFTutorial Notification Tutorial  Project With C# and MVVM
-----------------------------------------------------------

We are going to build our own C# notification app to demonstrate the power of PubNub messaging and a solution for WPF desktop notifications. Here is the file structure of the MVVM project:

![](https://images.ctfassets.net/3prze68gbwl1/FfGomoqHd2m9ZGyqYvFQS/dcd2e6ffe9856e1842f7b227573db292/wpf-pubnub-project.png)

_All of the code referenced in this tutorial is_ **_available open source on_** [**_GitHub_**](https://github.com/ajb413/wpf-pubnub-desktop-notifications)_._

_In order to get the app running, you need to get your_ **_forever free_** [**_PubNubAPI keys_**](https://dashboard.pubnub.com/signup)_._

Be sure to **add your Publish and Subscribe keys** to the source code!

**Building a desktop notification starting with MVVM**
------------------------------------------------------

1\. If you’re starting from scratch, open**Visual Studio** ([free](https://visualstudio.microsoft.com/vs/community/)), and create a new **WPF**web application. **Click File -> New -> Project**.

![](https://images.ctfassets.net/3prze68gbwl1/Cy9BHqBZ6O23j8ntXQ5xG/cd1c8e30743790662c6639dcf7d44116/wpf-new-project-1.png)

2\. Right Click on the new project file in the **Solution Explorer** and click **Manage NuGet Packages**. We have to **install PubNub** to continue.

![](https://images.ctfassets.net/3prze68gbwl1/33PqCdHI6MLEgUWfIqjKec/eb638d0eb4b331ea3efd210d13eaed9c/install-pubnub-sdk-csharp.png)

3\. Create the folders in the **root of the project** like referenced in the **screenshot** from earlier. These folders are **Model, View, and ViewModel**. In the View folder, create 2 new XAML windows, the **Main Window** and the **Notification Window**.

**Continuing the notification build with XAML**
-----------------------------------------------

Here is the XAML for the 2 view files that you created. This will **make the UI** of our parent and notification windows.

MainWindow.xaml

<Window x:Class="WPF\_PubNub.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:vm="clr-namespace:WPF\_PubNub.VM"
        xmlns:local="clr-namespace:WPF\_PubNub"  mc:Ignorable="d"        
  
        xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"
        xmlns:ei="http://schemas.microsoft.com/expression/2010/interactions"
         
     
        Title="{Binding WindowName}" Height="300" Width="400">
    <Window.DataContext>
        <vm:PubNubVM />
    </Window.DataContext>
    <i:Interaction.Triggers>
        <i:EventTrigger EventName="Loaded">
            <ei:CallMethodAction TargetObject="{Binding}" MethodName="MainWindowLoaded"/>
        </i:EventTrigger>
    </i:Interaction.Triggers>
    
    <!--Loaded="{Binding OnWindowLoaded}"-->
    <Grid  >
        <StackPanel Name="stackPanel2" Grid.Column="1" Grid.Row="0" Background="White" >
            <Border CornerRadius="5" BorderBrush="Gray" BorderThickness="2" HorizontalAlignment="Center" >
                <Button   Width="{Binding ButtonWidth}" 
                Height="{Binding ButtonHeight}" Content="{Binding ButtonContent}" Background="#FFF3F0F0">
                    <i:Interaction.Triggers>
                        <i:EventTrigger EventName="Click">
                            <ei:CallMethodAction TargetObject="{Binding}" MethodName="PublishMessage"/>
                        </i:EventTrigger>
                    </i:Interaction.Triggers>
                </Button>
            </Border>
        </StackPanel>
    </Grid>
</Window>

**NotificationWindow.xaml**

<Window x:Class="Toast.NotificationWindow"
        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"
        mc:Ignorable="d"  WindowStyle="None" 
        Height="116.783" Width="319.93" Background="#FF110505" >
    <Grid>
        <Grid RenderTransformOrigin="0,1" >
            <!-- Animation -->
            <Grid.Triggers>
                <EventTrigger RoutedEvent="FrameworkElement.Loaded">
                    <BeginStoryboard>
                        <Storyboard>
                            <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.RenderTransform).(ScaleTransform.ScaleY)">
                                <SplineDoubleKeyFrame KeyTime="0:0:0" Value="0"/>
                                <SplineDoubleKeyFrame KeyTime="0:0:0.5" Value="1"/>
                            </DoubleAnimationUsingKeyFrames>
                            <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Opacity)">
                                <SplineDoubleKeyFrame KeyTime="0:0:2" Value="1"/>
                                <SplineDoubleKeyFrame KeyTime="0:0:4" Value="0"/>
                            </DoubleAnimationUsingKeyFrames>
                        </Storyboard>
                    </BeginStoryboard>
                </EventTrigger>
            </Grid.Triggers>
            <Grid.RenderTransform>
                <ScaleTransform ScaleY="1" />
            </Grid.RenderTransform>
            <!-- Notification area -->
            <Border BorderThickness="1" Margin="0,0,0,10" Background="#FF17161F" BorderBrush="Black" CornerRadius="10">
                <StackPanel Margin="20,9">
                    <TextBlock TextWrapping="Wrap" Margin="21,5,23,5" x:Name="NotifText"
                          Foreground="White" Background="Black" Height="75"/>
                </StackPanel>
            </Border>
            <Image HorizontalAlignment="Left" Height="37" VerticalAlignment="Top" Width="42" Source="iconMail.JPG" Margin="0,16,0,0"/>
        </Grid>
        <Button BorderThickness="0" HorizontalAlignment="Left" Margin="270,0,0,0" Click="Button\_Click\_Close"
           VerticalAlignment="Top"  Background="{x:Null}" Width="42" Height="43">
            <Image Source="CloseBtn.JPG" Height="39" Width="28" />
        </Button>
    </Grid>
</Window>

### C# notification window code example

Here is the **C# Code Behind** code for the [notification window](https://github.com/ajb413/wpf-pubnub-desktop-notifications/blob/master/WPF_PubNub/View/NotificationWindow.xaml.cs). All of the code is UI specific. It is meant to resemble the “Toast” notification.

using System;
using System.Windows;
using System.Windows.Threading;
namespace Toast
{
    /// <summary>
    /// Interaction logic for NotificationWindow.xaml
    /// </summary>
    public partial class NotificationWindow : Window
    {
        public NotificationWindow()
        {
            InitializeComponent();
            Dispatcher.BeginInvoke(DispatcherPriority.ApplicationIdle, new Action(() =>
            {
                var workingArea = System.Windows.Forms.Screen.PrimaryScreen.WorkingArea;
                var transform = PresentationSource.FromVisual(this).CompositionTarget.TransformFromDevice;
                var corner = transform.Transform(new Point(workingArea.Right, workingArea.Bottom));
                Left = corner.X - ActualWidth;
                Top = corner.Y - ActualHeight;
            }));
        }
 
        //Close the notification window
        private void Button\_Click\_Close(object sender, RoutedEventArgs e)
        {
            Close();
        }
    }
}

**Last step to building your C#, WPF, and MVVM notification** 
--------------------------------------------------------------

1.  In the ViewModel folder create a **PubNubVM.cs**, class which will be the facilitator between the **Model code** and **View code**. The code for that file [can be found here](https://github.com/ajb413/wpf-pubnub-desktop-notifications/blob/master/WPF_PubNub/ViewModel/PubNubVM.cs).
    
2.  In the Model folder, create a **PubNubHelper.cs** class to interact with the PubNub publish/subscribe API. **Be sure to input your own free** [**PubNubAPI keys**](https://dashboard.pubnub.com/signup) **in the PubNub initialization code**.
    
3.  You can see the “\_\_YOUR\_PUBNUB\_PUBLISH\_KEY\_HERE\_\_” and “\_\_YOUR\_PUBNUB\_SUBSCRIBE\_KEY\_HERE\_\_” in the file. Replace those string literals with your keys.
    

using Newtonsoft.Json;
using PubnubApi;
using System;
using System.Windows;
using Toast;
namespace WPF\_PubNub.Model
{
    public class PubNubHelper
    {
        Pubnub pubnub;
        private readonly string ChannelName = "win-notification";
        public void Init()
        {
            //Init
            PNConfiguration pnConfiguration = new PNConfiguration
            {
                PublishKey = "\_\_YOUR\_PUBNUB\_PUBLISH\_KEY\_HERE\_\_",
                SubscribeKey = "\_\_YOUR\_PUBNUB\_SUBSCRIBE\_KEY\_HERE\_\_",
                Secure = true
            };
            pubnub = new Pubnub(pnConfiguration);
            //Subscribe
            pubnub.Subscribe<string>()
           .Channels(new string\[\] {
               ChannelName
           })
           .WithPresence()
           .Execute();
        }
        //Publish a message
        public void Publish()
        {
            JsonMsg Person = new JsonMsg
            {
                Name = "John Doe",
                Description = "Description",
                Date = DateTime.Now.ToString()
            };
            //Convert to string
            string arrayMessage = JsonConvert.SerializeObject(Person);
            pubnub.Publish()
                .Channel(ChannelName)
                .Message(arrayMessage)
                .Async(new PNPublishResultExt((result, status) => {}));
        }
        //listen to the channel
        public void Listen()
        {
            SubscribeCallbackExt listenerSubscribeCallack = new SubscribeCallbackExt(
            (pubnubObj, message) => {
                //Call the notification windows from the UI thread
                Application.Current.Dispatcher.Invoke(new Action(() => { 
                    //Show the message as a WPF window message like WIN-10 toast
                    NotificationWindow ts = new NotificationWindow();
                    //Convert the message to JSON
                    JsonMsg bsObj = JsonConvert.DeserializeObject<JsonMsg>(message.Message.ToString());
                    string messageBoxText = "Name: " + bsObj.Name + Environment.NewLine + "Description: " + bsObj.Description + Environment.NewLine + "Date: " + bsObj.Date;
                    ts.NotifText.Text = messageBoxText;
                    ts.Show();
                }));
            },
            (pubnubObj, presence) => {
                // handle incoming presence data
            },
            (pubnubObj, status) => {
                // the status object returned is always related to subscribe but could contain
                // information about subscribe, heartbeat, or errors
                // use the PNOperationType to switch on different options
            });
 
            pubnub.AddListener(listenerSubscribeCallack);
        }
    }
}

**Pro Tip: In the Model folder, you will also need the JsonMsg.cs class, which** [**can be found here**](https://github.com/ajb413/wpf-pubnub-desktop-notifications/blob/master/WPF_PubNub/Model/JsonMsg.cs)**. Be sure to add any NuGet packages that are referenced in the** [**WPF project file**](https://github.com/ajb413/wpf-pubnub-desktop-notifications/blob/master/WPF_PubNub/WPF_PubNub.csproj)**. There are also some JPG image files for** [**the View folder**](https://github.com/ajb413/wpf-pubnub-desktop-notifications/tree/master/WPF_PubNub/View)**. These images appear in the custom-made notification window. Be sure to add them to the project View folder.**

4\. Run the project! Click the “Trigger Notification Window” button. You will notice a custom notification appear in the lower right-hand corner of your desktop! This is powered by PubNub, so if you have this application running on multiple machines, the notification will appear on every machine, for each individual button click.

![](https://images.ctfassets.net/3prze68gbwl1/6uxw74cdFfaWHFIVIeT1a/ab14d1b074bda88a5d335a8069df95bc/pubnub-wpf-window.png)

By using other [PubNubSDKs](https://www.pubnub.com/docs/sdks) and client devices, the notification system is language/device agnostic.

### **Getting Started with Desktop Toast Notifications**

This desktop notification pattern can be modified for custom push notifications intended to improve the user experience. It can be achieved by using multiple channels, and also with [Access Manager](https://www.pubnub.com/docs/security/access-control), to secure who can read/write to specific channels.

For more C# code examples, reach out to [devrel@pubnub.com](mailto:devrel@pubnub.com) or check out our [docs](https://www.pubnub.com/docs) and [developer resources](https://www.pubnub.com/developers/) to help speed up your app development!

How can PubNub help you?
========================

This article was originally published on [PubNub.com](https://www.pubnub.com/blog/c-sharp-desktop-notifications-wpf-mvvm/)

Our platform helps developers build, deliver, and manage real-time interactivity for web apps, mobile apps, and IoT devices.

The foundation of our platform is the industry's largest and most scalable real-time edge messaging network. With over 15 points-of-presence worldwide supporting 800 million monthly active users, and 99.999% reliability, you'll never have to worry about outages, concurrency limits, or any latency issues caused by traffic spikes.

Experience PubNub
-----------------

Check out [Live Tour](https://www.pubnub.com/tour/introduction/) to understand the essential concepts behind every PubNub-powered app in less than 5 minutes

Get Setup
---------

Sign up for a [PubNub account](https://admin.pubnub.com/signup/) for immediate access to PubNub keys for free

Get Started
-----------

The [PubNub docs](https://www.pubnub.com/docs) will get you up and running, regardless of your use case or [SDK](https://www.pubnub.com/docs)