Universal Windows Platform – Adaptable Toast

Adaptable Toast demonstrates how to use Adaptive Toast Notifications to display Toast Notifications in the Action Centre in Windows 10

Step 1

If not already, follow Setup and Start on how to Install and get Started with Visual Studio 2017 or in Windows 10 choose Start, and then from the Start Menu find and select Visual Studio 2017.

vs2017

Step 2

Once Visual Studio Community 2017 has started, from the Menu choose File, then New then Project…

vs2017-file-new-project

Step 3

From New Project choose Visual C# from Installed, Templates then choose Blank App (Universal Windows) and then type in a Name and select a Location and then select Ok to create the Project
vs2017-new-project-window

Step 4

Then in New Universal Windows Project you need to select the Target Version this should be at least the Windows 10, version 1803 (10.0; Build 17134) which is the April 2018 Update and the Minimum Version to be the same.

vs2017-target-platform

The Target Version will control what features your application can use in Windows 10 so by picking the most recent version you’ll be able to take advantage of those features. To make sure you always have the most recent version, in Visual Studio 2017 select Tools Extensions and Updates… then and then see if there are any Updates

Step 5

From the Menu choose Tools, then NuGet Package Manager and Package Manager Console

vs2017-package-manager-console-font-control

Step 6

Then in the Package Manager Console Window which usually appears at the bottom of Visual Studio 2017 at the PM> Prompt type in following:

 
Install-Package Microsoft.Toolkit.Uwp.Notifications

vs2017-package-manager-console-adaptable-toast

Followed by typing Enter to install Microsoft.Toolkit.Uwp.Notifications from NuGet into the Application which should be Successfully installed

Step 7

Once done select from the Menu, Project, then Add New Item…

vs2017-project-add-new-item

Step 8

From the Add New Item window select Visual C#, then Code from Installed then select Code File from the list, then type in the Name as Library.cs before selecting Add to add the file to the Project

vs2017-add-new-item-library

Step 9

Once in the Code View for Library.cs the following should be entered:

using Microsoft.Toolkit.Uwp.Notifications;
using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Linq;
using System.Threading.Tasks;
using System.Web;
using Windows.ApplicationModel.Activation;
using Windows.Foundation;
using Windows.UI.Notifications;
using Windows.UI.Popups;
using Windows.UI.Xaml.Controls;

public class AdaptableItem
{
    private const string key_id = "id";
    private const string key_title = "title";
    private const string key_body = "body";

    private string CreateQueryString(Dictionary<string, string> source)
    {
        string[] array = source.Select(kv =>
        $"{HttpUtility.UrlEncode(kv.Key)}={HttpUtility.UrlEncode(kv.Value)}").ToArray();
        return $"?{string.Join("&", array)}";
    }

    private Dictionary<string, string> ParseQueryString(string query)
    {
        NameValueCollection value = HttpUtility.ParseQueryString(query);
        return value.AllKeys.ToDictionary(x => HttpUtility.UrlDecode(x),
        x => HttpUtility.UrlDecode(value[x]));
    }

    public string Id { get; set; }
    public string Title { get; set; }
    public string Body { get; set; }

    public AdaptableItem() { }

    public AdaptableItem(string value)
    {
        Dictionary<string, string> dict = ParseQueryString(value);
        Id = dict[key_id];
        Title = dict[key_title];
        Body = dict[key_body];
    }

    public string Create()
    {
        Dictionary<string, string> dict = new Dictionary<string, string>()
        {
            { key_id, this.Id },
            { key_title, this.Title },
            { key_body, this.Body }
        };
        return CreateQueryString(dict);
    }

    public override string ToString()
    {
        return $"Id: {Id}, Title: {Title}, Body: {Body}";
    }
}

public class Toast
{
    private readonly Random random = new Random((int)DateTime.Now.Ticks);

    private ToastNotification GetNotification(AdaptableItem item)
    {
        ToastContent content = new ToastContent()
        {
            Launch = item.Create(),
            Visual = new ToastVisual()
            {
                BindingGeneric = new ToastBindingGeneric()
                {
                    AppLogoOverride = new ToastGenericAppLogo()
                    {
                        Source = "ms-appx:///Assets/StoreLogo.png"
                    },
                    Children =
                    {
                        new AdaptiveText()
                        {
                            Text = item.Title,
                            HintStyle = AdaptiveTextStyle.Body
                        },
                        new AdaptiveText()
                        {
                            Text = item.Body,
                            HintWrap = true,
                            HintStyle = AdaptiveTextStyle.CaptionSubtle
                        }
                    }
                }
            }
        };
        return new ToastNotification(content.GetXml());
    }

    public AdaptableItem Show(string title, string body)
    {
        string id = random.Next(1, 100000000).ToString();
        AdaptableItem item = new AdaptableItem() { Id = id, Title = title, Body = body };
        ToastNotification notification = GetNotification(item);
        ToastNotificationManager.CreateToastNotifier().Show(notification);
        return item;
    }
}

public static class Library
{
    private const string app_title = "Adaptable Toast";
    private static readonly Toast toast = new Toast();

    private static IAsyncOperation<IUICommand> _dialogCommand;

    private static async Task<bool> ShowDialogAsync(string content, string title = app_title)
    {
        try
        {
            if (_dialogCommand != null)
            {
                _dialogCommand.Cancel();
                _dialogCommand = null;
            }
            _dialogCommand = new MessageDialog(content, title).ShowAsync();
            await _dialogCommand;
            return true;
        }
        catch (TaskCanceledException)
        {
            return false;
        }
    }

    public static async void Activated(ToastNotificationActivatedEventArgs args)
    {
        if (args != null)
        {
            string argument = args.Argument;
            await ShowDialogAsync($"Selected - {new AdaptableItem(argument)}");
        }
    }

    public static void Add(TextBox title, TextBox desc)
    {
        toast.Show(title.Text, desc.Text);
    }
}

In the Code File for Library there are using statements to include the necessary functionality. There is also a AdaptableItem Class with const for Keys, a CreateQueryString to convert a Dictionary of string and string to a Query String, there is a ParseQueryString to convert a Query String back to a Dictionary of string and string. There are also Properties for Id, Colour, Title and Body. The CreateMethod will produce a Query String from a the AdaptableItem using a Dictionary of string and string and the ToString Method produces a string representation of the AdaptableItem Class Object.

The Toast Class has a Random to produce randomised numeric values, a GetNotification Method to create a ToastNotification which uses ToastContent from the Microsoft.Toolkit.Uwp.Notifications Package and there is an Show Method which will create a AdaptableItem with an Id using Random and then with the ToastNotificationManager call Show on the CreateToastNotifier to show the ToastNotification for the Application.

The Library Class has const and readonly Values including an Instance of the Toast Class and has an IAsyncOperation of IUICommand for use with the ShowDialogAsync Method which will display a MessageDialog. There is a Activated Method which will check the TileActivatedInfo from the passed in ToastNotificationActivatedEventArgs get the Argument and use ShowDialogAsync with a created AdaptableItem to display its details in a MessageDialog. Then there is an Add Method which will call the Show Method of the Toast Class which will display the ToastNotification.

Step 10

In the Solution Explorer select App.xaml

vs2017-app-library

Step 11

From the Menu choose View and then Code

vs2017-view-code

Step 12

Once in the Code View below private void OnSuspending(object sender, SuspendingEventArgs e) { … } the following should be entered:

protected override void OnActivated(IActivatedEventArgs e)
{
	base.OnActivated(e);
	try
	{
		if (e.Kind == ActivationKind.ToastNotification)
		{
			Library.Activated(e as ToastNotificationActivatedEventArgs);
		}
	}
	catch { }
	Frame rootFrame = Window.Current.Content as Frame;
	if (rootFrame == null)
	{
		rootFrame = new Frame();
		rootFrame.NavigationFailed += OnNavigationFailed;
		Window.Current.Content = rootFrame;
	}
	if (rootFrame.Content == null)
	{
		rootFrame.Navigate(typeof(MainPage), e);
	}
	Window.Current.Activate();
}

The OnActivated Event Handler will be triggered when the Toast Notification Launches the application which is ActivationKind.ToastNotification and then the ToastNotificationActivatedEventArgs Implementation of IActivatedEventArgs will be obtained and passed to the the Activated Method of the Library Class will be called, because the static Keyword is used it is not necessary to use new to create an Instance of the Library Class before calling this Method.

Step 13

In the Solution Explorer select MainPage.xaml

vs2017-mainpage-library

Step 14

From the Menu choose View and then Designer

vs2017-view-designer

Step 15

The Design View will be displayed along with the XAML View and in this between the Grid and /Grid elements, enter the following XAML:

<Grid Margin="50">
	<Grid.ColumnDefinitions>
		<ColumnDefinition Width="50*"/>
		<ColumnDefinition Width="50*"/>
	</Grid.ColumnDefinitions>
	<TextBox Name="Title" Grid.Column="0" PlaceholderText="Title" Margin="20" VerticalAlignment="Top"/>
	<TextBox Name="Body" Grid.Column="1" PlaceholderText="Body" Margin="20" VerticalAlignment="Top"/>
</Grid>
<CommandBar Name="Command" VerticalAlignment="Bottom">
	<AppBarButton Icon="Add" Label="Add" Click="Add_Click"/>
</CommandBar>

Within the main Grid Element, the first block of XAML is a Grid Control which has two Columns which are TextBox Controls in a Column each for Title and Body. The second block of XAML is a CommandBar with an AppBarButton for Add which calls Add_Click.

Step 16

From the Menu choose View and then Code

vs2017-view-code

Step 17

Once in the Code View, below the end of public MainPage() { … } the following Code should be entered:

private void Add_Click(object sender, RoutedEventArgs e)
{
	Library.Add(Title, Body);
}

Below the MainPage() there is an Add_Click Event Handler which calls the Add Method in the Library Class and again because the static Keyword is used it is not necessary to use new to create an Instance of the Library Class before calling this Method.

Step 18

That completes the Universal Windows Platform Application so Save the Project then in Visual Studio select the Local Machine to run the Application

vs2017-local-machine

Step 19

After the Application has started running you can then type into the TextBox for Title and Body then select Add to display the Toast Notification

ran-adaptable-toast

Step 20

To Exit the Application select the Close button in the top right of the Application

vs2017-close

Adaptable Toast shows how to create an Adaptive Toast with the NuGet Package for Microsoft.Toolkit.Uwp.Notifications to create a ToastNotification and then respond to this in an Application when Launched from the ToastNotification.

Creative Commons License

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s