Quickstart: Sending a weather Tile and Toast Notification

In the Anniversary Update of Windows 10, we've made Toast Notifications as visually-capable as Live Tiles. In this Quickstart, we'll show you how can re-use your Tile Notification's 5-day weather forecast to send a Toast Notification displaying the forecast.

Wide Live Tile Toast Notification

1. Install UWP Community Toolkit NuGet package

In order to create notifications via code, we strongly recommend using the UWP Community Toolkit Notifications library, which provides an object model for the notification XML content. You could manually construct the notification XML, but that is error-prone and messy. The Notifications library is built and maintained by the team that owns notifications at Microsoft.

Install Microsoft.Toolkit.Uwp.Notifications from NuGet (we're using version 1.0.0 in this documentation).

2. Add namespace declarations

Windows.UI.Notifications includes the Tile and Toast API's.

 
using Microsoft.Toolkit.Uwp.Notifications;
using Windows.UI.Notifications;

3. How to create the Live Tile

We will first explain how the Live Tile is created, since similar Adaptive content is used on the Toast Notification. If you're new to Adaptive Notifications, install Notifications Visualizer from the Store, which allows you to edit Adaptive content and see an instant visual preview.

Dissect the Tile Notification into Subgroups

The Tile Notification that we want to create is actually just 5 subgroups... one for each day's forecast. In the picture below, the second subgroup is highlighted in red. We can create a method that generates these subgroups, so that we only write the subgroup code once.

 
private AdaptiveSubgroup GenerateSubgroup(string day, string img, int tempHi, int tempLo)
{
    return new AdaptiveSubgroup()
    {
        HintWeight = 1,

        Children =
        {
            // Day
            new AdaptiveText()
            {
                Text = day,
                HintAlign = AdaptiveTextAlign.Center
            },

            // Image
            new AdaptiveImage()
            {
                Source = img,
                HintRemoveMargin = true
            },

            // High temp
            new AdaptiveText()
            {
                Text = tempHi + "°",
                HintAlign = AdaptiveTextAlign.Center
            },

            // Low temp
            new AdaptiveText()
            {
                Text = tempLo + "°",
                HintAlign = AdaptiveTextAlign.Center,
                HintStyle = AdaptiveTextStyle.CaptionSubtle
            }
        }
    };
}

Generate content for the Wide Tile

Next, we need to construct the actual content for the Wide Tile, using our subgroups from above. We break this out into a separate method, since we'll also need methods for creating the Small Tile content, and Wide and Large (these methods are omitted from this Quickstart but can be seen in the full code sample available in the Resources at the bottom).

 
private TileBinding GenerateTileBindingWide()
{
    return new TileBinding()
    {
        Content = new TileBindingContentAdaptive()
        {
            Children =
            {
                new AdaptiveGroup()
                {
                    Children =
                    {
                        GenerateSubgroup("Mon", "Mostly Cloudy.png", 63, 42),
                        GenerateSubgroup("Tue", "Cloudy.png", 57, 38),
                        GenerateSubgroup("Wed", "Sunny.png", 59, 43),
                        GenerateSubgroup("Thu", "Sunny.png", 62, 42),
                        GenerateSubgroup("Fri", "Sunny.png", 71, 66)
                    }
                }
            }
        }
    };
}

Generate the Tile Notification content

Finally, we generate the entire Tile Notification's content, which will contain content for all the various sizes of the tile. As we mentioned earlier, the methods for Small, Medium, and Large are omitted from this Quickstart but can be seen in the full code sample available in the Resources section.

 
public TileContent GenerateTileContent()
{
    return new TileContent()
    {
        Visual = new TileVisual()
        {
            TileSmall = GenerateTileBindingSmall(),
            TileMedium = GenerateTileBindingMedium(),
            TileWide = GenerateTileBindingWide(),
            TileLarge = GenerateTileBindingLarge(),

            // Set the base URI for the images, so we don't redundantly specify the entire path
            BaseUri = new Uri("Assets/NotificationAssets/", UriKind.Relative)
        }
    };
}

Sending the Tile Notification

To learn how to send a Tile Notification, please see Quickstart: Sending a local tile notification.

4. How to create the Toast Notification

Now that we have our Live Tile Notification, let's use some of that code to create the Toast Notification!

Construct the Toast Notification content

Toasts must always start with a text element, so we first add a text string describing today's weather. If Adaptive Toasts are supported (see further below for the code), we add a group with the five subgroups that we also used for our Live Tile. Otherwise, we just add two more text elements for systems that don't support Adaptive Toast (note that on those systems, you can only have a max of three text elements, hence why we only added two additional text elements).

 
public static ToastContent GenerateToastContent()
{
    // Start by constructing the visual portion of the toast
    ToastBindingGeneric binding = new ToastBindingGeneric();

    // We'll always have this summary text on our toast notification
    // (it is required that your toast starts with a text element)
    binding.Children.Add(new AdaptiveText()
    {
        Text = "Today will be mostly sunny with a high of 63 and a low of 42."
    });

    // If Adaptive Toast Notifications are supported
    if (IsAdaptiveToastSupported())
    {
        // Use the rich Tile-like visual layout
        binding.Children.Add(new AdaptiveGroup()
        {
            Children =
            {
                GenerateSubgroup("Mon", "Mostly Cloudy.png", 63, 42),
                GenerateSubgroup("Tue", "Cloudy.png", 57, 38),
                GenerateSubgroup("Wed", "Sunny.png", 59, 43),
                GenerateSubgroup("Thu", "Sunny.png", 62, 42),
                GenerateSubgroup("Fri", "Sunny.png", 71, 66)
            }
        });
    }

    // Otherwise...
    else
    {
        // We'll just add two simple lines of text
        binding.Children.Add(new AdaptiveText()
        {
            Text = "Monday ⛅ 63° / 42°"
        });

        binding.Children.Add(new AdaptiveText()
        {
            Text = "Tuesday ☁ 57° / 38°"
        });
    }

    // Construct the entire notification
    return new ToastContent()
    {
        Visual = new ToastVisual()
        {
            // Use our binding from above
            BindingGeneric = binding,

            // Set the base URI for the images, so we don't redundantly specify the entire path
            BaseUri = new Uri("Assets/NotificationAssets/", UriKind.Relative)
        },

        // Include launch string so we know what to open when user clicks toast
        Launch = "action=viewForecast&zip=98008"
    };
}

Sending the Toast Notification

To learn how to send the Toast Notification (and how to handle the user clicking the notification), please see Quickstart: Sending a local toast notification and handling activations.

Checking if Adaptive Toast is supported

Adaptive Toasts were added in build 14332 of Windows 10 Desktop and Mobile (for the Anniversary Update of Windows 10). Other device families do not support Adaptive Toasts, and can only contain text elements and images. If you are supporting older systems, you have two options: Send the same payload (the groups will simply be dropped on older systems), or fork your code and send specific notifications based on whether Adaptive Toast is supported. Here's the method we use to tell whether we can send visually-rich notifications...

 
using Windows.System.Profile;

private static bool IsAdaptiveToastSupported()
{
    switch (AnalyticsInfo.VersionInfo.DeviceFamily)
    {
        // Desktop and Mobile started supporting adaptive toasts in build 14332
        case "Windows.Mobile":
        case "Windows.Desktop":
            return GetOSVersion() > new Version(10, 0, 14332, 0);

        // Other device families do not support adaptive toasts
        default:
            return false;
    }
}

private static Version GetOSVersion()
{
    // The DeviceFamilyVersion is a string, which is actually a ulong number representing the version 
    // https://www.suchan.cz/2015/08/uwp-quick-tip-getting-device-os-and-app-info/ 

    ulong versionAsLong = ulong.Parse(AnalyticsInfo.VersionInfo.DeviceFamilyVersion);

    ulong v1 = (versionAsLong & 0xFFFF000000000000L) >> 48;
    ulong v2 = (versionAsLong & 0x0000FFFF00000000L) >> 32;
    ulong v3 = (versionAsLong & 0x00000000FFFF0000L) >> 16;
    ulong v4 = (versionAsLong & 0x000000000000FFFFL);

    return new Version((int)v1, (int)v2, (int)v3, (int)v4);
}

Final Toast Notification!

For systems that support Adaptive Toast, our code generates the visually-rich notification. And for older systems, our code generates the classic text-driven notification.

Adaptive Toast Classic Toast

Resources