posts - 615, comments - 10486, trackbacks - 594, articles - 0
  博客园 :: 首页 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理

公告

背水一战 Windows 10 (103) - 通知(Toast): 基础, 按计划显示 toast 通知

Posted on 2018-06-20 09:03 webabcd 阅读(...) 评论(...) 编辑 收藏

[源码下载]


背水一战 Windows 10 (103) - 通知(Toast): 基础, 按计划显示 toast 通知



作者:webabcd


介绍
背水一战 Windows 10 之 通知(Toast)

  • 基础
  • 按计划显示 toast 通知



示例
1、本例用于演示当通过 toast 激活 app 时(前台方式激活),如何获取相关信息
Notification/Toast/Demo.xaml

<Page
    x:Class="Windows10.Notification.Toast.Demo"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:Windows10.Notification.Toast"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d">

    <Grid Background="Blue">

        <TextBlock Name="lblMsg" VerticalAlignment="Center" HorizontalAlignment="Center" />

    </Grid>
</Page>

Notification/Toast/Demo.xaml.cs

/*
 * 本例用于演示当通过 toast 激活 app 时(前台方式激活),如何获取相关信息
 * 
 * 
 * 在 App.xaml.cs 中 override void OnActivated(IActivatedEventArgs args),以获取相关的 toast 信息
 * 
 * ToastNotificationActivatedEventArgs - 通过 toast 激活应用程序时(前台方式激活)的事件参数
 *     Argument - 由 toast 传递过来的参数
 *     UserInput - 由 toast 传递过来的输入框数据
 *     Kind - 此 app 被激活的类型(ActivationKind 枚举)
 *         比如,如果是通过“打开文件”激活的话,则此值为 File
 *     PreviousExecutionState - 此 app 被激活前的状态(ApplicationExecutionState 枚举)
 *         比如,如果此 app 被激活前就是运行状态的或,则此值为 Running
 *     SplashScreen - 获取此 app 的 SplashScreen 对象
 *     User - 获取激活了此 app 的 User 对象
 */

using System;
using Windows.ApplicationModel.Activation;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Navigation;

namespace Windows10.Notification.Toast
{
    public sealed partial class Demo : Page
    {
        private ToastNotificationActivatedEventArgs _toastArgs;

        public Demo()
        {
            this.InitializeComponent();
        }

        protected override void OnNavigatedTo(NavigationEventArgs e)
        {
            // 获取 ToastNotificationActivatedEventArgs 对象(从 App.xaml.cs 传来的)
            _toastArgs = e.Parameter as ToastNotificationActivatedEventArgs;

            if (_toastArgs != null)
            {
                // 获取 toast 的参数
                lblMsg.Text = "argument: " + _toastArgs.Argument;
                lblMsg.Text += Environment.NewLine;

                // 获取 toast 的 输入框数据
                // UserInput 是一个 ValueSet 类型的数据,其继承自 IEnumerable 接口,可以 foreach(不能 for)
                foreach (string key in _toastArgs.UserInput.Keys)
                {
                    lblMsg.Text += $"key:{key}, value:{_toastArgs.UserInput[key]}";
                    lblMsg.Text += Environment.NewLine;
                }
            }
        }
    }
}


2、本例用于演示 toast 的基础
Notification/Toast/Basic.xaml

<Page
    x:Class="Windows10.Notification.Toast.Basic"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:Windows10.Notification.Toast"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d">

    <Grid Background="Transparent">
        <StackPanel Margin="10 0 10 10">

            <Button Name="buttonShowToast1" Content="显示 toast" Click="buttonShowToast1_Click" Margin="5" />

            <Button Name="buttonShowToast2" Content="显示 toast(设置 toast 的过期时间)" Click="buttonShowToast2_Click" Margin="5" />

            <Button Name="buttonShowToast3" Content="显示 toast(无 toast 通知 UI,仅放置于操作中心)" Click="buttonShowToast3_Click" Margin="5" />

        </StackPanel>
    </Grid>
</Page>

Notification/Toast/Basic.xaml.cs

/*
 * 本例用于演示 toast 的基础
 * 单击 toast 激活 app 后(前台方式激活),如何获取相关信息请参见 Demo.xaml.cs 中的代码
 * 
 * 
 * ToastNotification - toast 通知
 *     Content - 一个 Windows.Data.Xml.Dom.XmlDocument 类型的对象(在构造函数中需要传递此对象),用于描述 toast 的 xml
 *     SuppressPopup - 默认值为 false
 *         false - 弹出 toast 通知,并放置于操作中心
 *         true - 不弹出 toast 通知,仅放置于操作中心
 *     ExpirationTime - 过期时间,超过这个时间就会从操作中心中移除
 *     ToastNotificationPriority - 优先级(Default 或 High)
 *     Group, Tag - 用于标识 toast 对象(前 16 个字符相同则认为相同)
 *         同 group 且同 tag 则视为同一 toast,即新 toast 会更新旧 toast
 *         系统会将所用未指定 group 的 toast 视为同 group
 *         系统会将所用未指定 tag 的 toast 视为不同 tag
 *     Activated - 通过 toast 激活 app 时触发的事件
 *     Dismissed - 弹出的 toast 通知 UI 消失时触发的事件
 *     Failed - 弹出 toast 通知时失败
 *     
 * ToastNotificationManager - toast 通知管理器
 *     CreateToastNotifier() - 创建 ToastNotifier 对象
 *     History - 获取 ToastNotificationHistory 对象
 *     
 * ToastNotifier - toast 通知器
 *     Show(ToastNotification notification) - 弹出指定的 toast 通知
 *     Hide(ToastNotification notification) - 移除指定的 toast 通知
 *     Setting - 获取系统的通知设置
 *         Enabled - 通知可被显示
 *         DisabledForApplication - 用户禁用了此应用程序的通知
 *         DisabledForUser - 用户禁用了此计算机此账户的所有通知
 *         DisabledByGroupPolicy - 管理员通过组策略禁止了此计算机上的所有通知
 *         DisabledByManifest - 应用程序未在 Package.appxmanifest 中设置“应用图标”(其实你要是不设置的话编译都不会通过)
 *         
 * ToastNotificationHistory - 本 app 的 toast 通知历史
 *     Clear() - 全部清除(从操作中心中移除)
 *     RemoveGroup() - 清除指定 group 的通知(从操作中心中移除)
 *     Remove() - 清除指定 tag 的通知或清除指定 tag 和 group 的通知(从操作中心中移除)
 *     GetHistory() - 获取历史数据,一个 ToastNotification 类型对象的集合(已被从操作中心中移除的是拿不到的)
 *     
 *     
 *     
 * 注:本例是通过 xml 来构造 toast 的,另外也可以通过 NuGet 的 Microsoft.Toolkit.Uwp.Notifications 来构造 toast(其用 c# 对 xml 做了封装)
 */

using System;
using System.Diagnostics;
using Windows.Data.Xml.Dom;
using Windows.UI.Notifications;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;

namespace Windows10.Notification.Toast
{
    public sealed partial class Basic : Page
    {
        public Basic()
        {
            this.InitializeComponent();
        }

        // 弹出 toast 通知
        private void buttonShowToast1_Click(object sender, RoutedEventArgs e)
        {
            // 清除本 app 的之前的全部 toast 通知
            // ToastNotificationManager.History.Clear();

            // 用于描述 toast 通知的 xml 字符串
            string toastXml = $@"
                <toast activationType='foreground' launch='Notification-Toast-Basic-Arguments 1'>
                    <visual>
                        <binding template='ToastGeneric'>
                            <text>toast - title</text>
                            <text>toast - content 1 {DateTime.Now.ToString("mm:ss")}</text>
                        </binding>
                    </visual>
                </toast>";

            // 将 xml 字符串转换为 Windows.Data.Xml.Dom.XmlDocument 对象
            XmlDocument toastDoc = new XmlDocument();
            toastDoc.LoadXml(toastXml);

            // 实例化 ToastNotification 对象
            ToastNotification toast = new ToastNotification(toastDoc);
            // 系统会将所用未指定 group 的 toast 视为同 group
            // 同 group 且同 tag 则视为同一 toast,即新 toast 会更新旧 toast
            toast.Tag = "1";

            toast.Activated += Toast_Activated;
            toast.Dismissed += Toast_Dismissed;
            toast.Failed += Toast_Failed;

            // 弹出 toast 通知
            ToastNotifier toastNotifier = ToastNotificationManager.CreateToastNotifier();
            toastNotifier.Show(toast);
        }

        // 弹出 toast 通知(设置 toast 的过期时间)
        private void buttonShowToast2_Click(object sender, RoutedEventArgs e)
        {
            // 清除本 app 的之前的全部 toast 通知
            // ToastNotificationManager.History.Clear();

            string toastXml = $@"
                <toast activationType='foreground' launch='Notification-Toast-Basic-Arguments 2'>
                    <visual>
                        <binding template='ToastGeneric'>
                            <text>toast - title</text>
                            <text>toast - content 2 {DateTime.Now.ToString("mm:ss")}</text>
                        </binding>
                    </visual>
                </toast>";

            XmlDocument toastDoc = new XmlDocument();
            toastDoc.LoadXml(toastXml);

            ToastNotification toast = new ToastNotification(toastDoc);
            DateTimeOffset expirationTime = DateTimeOffset.UtcNow.AddSeconds(30);
            toast.ExpirationTime = expirationTime; // 30 秒后 toast 通知将从操作中心中移除

            // 系统会将所用未指定 group 的 toast 视为同 group
            // 系统会将所用未指定 tag 的 toast 视为不同 tag(此时虽然获取 tag 时其为空字符串,但是系统会认为其是一个随机值)
            // 每次弹出此 toast 时都会被认为是一个全新的 toast
            // toast.Tag = "2";

            toast.Activated += Toast_Activated;
            toast.Dismissed += Toast_Dismissed;
            toast.Failed += Toast_Failed;

            ToastNotifier toastNotifier = ToastNotificationManager.CreateToastNotifier();
            toastNotifier.Show(toast);
        }

        // 弹出 toast 通知(无 toast 通知 UI,仅放置于操作中心)
        private void buttonShowToast3_Click(object sender, RoutedEventArgs e)
        {
            // 清除本 app 的之前的全部 toast 通知
            // ToastNotificationManager.History.Clear();

            string toastXml = $@"
                <toast activationType='foreground' launch='Notification-Toast-Basic-Arguments 3'>
                    <visual>
                        <binding template='ToastGeneric'>
                            <text>toast - title</text>
                            <text>toast - content 3 {DateTime.Now.ToString("mm:ss")}</text>
                        </binding>
                    </visual>
                </toast>";

            XmlDocument toastDoc = new XmlDocument();
            toastDoc.LoadXml(toastXml);

            ToastNotification toast = new ToastNotification(toastDoc);
            toast.SuppressPopup = true; // 不会弹出 toast 通知 UI,但是会放置于操作中心
            toast.Tag = "3";

            toast.Activated += Toast_Activated;
            toast.Dismissed += Toast_Dismissed;
            toast.Failed += Toast_Failed;

            ToastNotifier toastNotifier = ToastNotificationManager.CreateToastNotifier();
            toastNotifier.Show(toast);
        }


        private void Toast_Activated(ToastNotification sender, object args)
        {
            Debug.WriteLine(sender.Tag + " Toast_Activated");
        }

        private void Toast_Dismissed(ToastNotification sender, ToastDismissedEventArgs args)
        {
            Debug.WriteLine(sender.Tag + " Toast_Dismissed");
        }

        private void Toast_Failed(ToastNotification sender, ToastFailedEventArgs args)
        {
            Debug.WriteLine(sender.Tag + " Toast_Failed");
        }
    }
}


3、演示如何按计划显示 toast 通知(在指定的时间显示指定的 toast 通知)
Notification/Toast/Schedule.xaml

<Page
    x:Class="Windows10.Notification.Toast.Schedule"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:Windows10.Notification.Toast"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d">

    <Grid Background="Transparent">
        <StackPanel Margin="10 0 10 10">

            <!--显示当前 app 的全部 ScheduledToastNotification 对象列表-->
            <ListBox Name="listBox" Width="800" Height="400" Margin="5" HorizontalAlignment="Left">
                <ListBox.ItemTemplate>
                    <DataTemplate>
                        <StackPanel Orientation="Horizontal">
                            <TextBlock Text="{Binding Id}" VerticalAlignment="Center" />
                            <TextBlock Text="{Binding Tag}" Margin="15 0 0 0" VerticalAlignment="Center" />
                            <HyperlinkButton Name="btnRemoveScheduledToast" Content="删除此 ScheduledToastNotification" Tag="{Binding Id}" Margin="15 0 0 0" Click="btnRemoveScheduledToast_Click" />
                        </StackPanel>
                    </DataTemplate>
                </ListBox.ItemTemplate>
            </ListBox>

            <Button Name="btnAddScheduledToast" Content="添加指定的 ScheduledToastNotification 到计划列表中" Click="btnAddScheduledToast_Click" Margin="5" />

        </StackPanel>
    </Grid>
</Page>

Notification/Toast/Schedule.xaml.cs

/*
 * 演示如何按计划显示 toast 通知(在指定的时间显示指定的 toast 通知)
 * 
 * ScheduledToastNotification - 按计划显示 Toast 通知
 *     Content - Toast 的内容,XmlDocument 类型的数据,只读,其需要在构造函数中指定
 *     DeliveryTime - 显示 Toast 通知的时间,只读,其需要在构造函数中指定
 *     SnoozeInterval - 循环显示 Toast 通知的间隔时长(60 秒 - 60 分之间),只读,其需要在构造函数中指定(经测试,此逻辑无效)
 *     MaximumSnoozeCount - 循环的最大次数(1 - 5 次),只读,其需要在构造函数中指定(经测试,此逻辑无效)
 *     Id - ScheduledToastNotification 的标识
 *     Group, Tag - 用于标识 toast 对象(前 16 个字符相同则认为相同)
 *         同 group 且同 tag 则视为同一 toast,即新 toast 会更新旧 toast
 *         系统会将所用未指定 group 的 toast 视为同 group
 *         系统会将所用未指定 tag 的 toast 视为不同 tag
 *     SuppressPopup - 默认值为 false
 *         false - 弹出 toast 通知,并放置于操作中心
 *         true - 不弹出 toast 通知,仅放置于操作中心
 *     
 * ToastNotifier - toast 通知器
 *     AddToSchedule() - 将指定的 ScheduledToastNotification 对象添加到计划列表
 *     RemoveFromSchedule() - 从计划列表中移除指定的 ScheduledToastNotification 对象
 *     GetScheduledToastNotifications() - 获取当前 app 的全部 ScheduledToastNotification 对象列表
 */

using System;
using System.Collections.Generic;
using Windows.Data.Xml.Dom;
using Windows.UI.Notifications;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Navigation;

namespace Windows10.Notification.Toast
{
    public sealed partial class Schedule : Page
    {
        public Schedule()
        {
            this.InitializeComponent();
        }

        protected override void OnNavigatedTo(NavigationEventArgs e)
        {
            ShowScheduledToasts();
        }

        // 添加指定的 ScheduledToastNotification 到计划列表中
        private void btnAddScheduledToast_Click(object sender, RoutedEventArgs e)
        {
            string toastXml = $@"
                <toast activationType='foreground' launch='Notification-Toast-Schedule-Arguments'>
                    <visual>
                        <binding template='ToastGeneric'>
                            <text>toast - title</text>
                            <text>toast - content {DateTime.Now.ToString("mm:ss")}</text>
                        </binding>
                    </visual>
                </toast>";

            // 将 xml 字符串转换为 Windows.Data.Xml.Dom.XmlDocument 对象
            XmlDocument toastDoc = new XmlDocument();
            toastDoc.LoadXml(toastXml);

            // 实例化 ScheduledToastNotification 对象(15 秒后显示此 Toast 通知,然后每隔 60 秒再显示一次 Toast,循环显示 5 次)
            // 但是经测试,只会显示一次,无法循环显示,不知道为什么
            // ScheduledToastNotification toastNotification = new ScheduledToastNotification(toastDoc, DateTime.Now.AddSeconds(15), TimeSpan.FromSeconds(60), 5);

            // 实例化 ScheduledToastNotification 对象(15 秒后显示此 Toast 通知)
            ScheduledToastNotification toastNotification = new ScheduledToastNotification(toastDoc, DateTime.Now.AddSeconds(15));

            toastNotification.Id = new Random().Next(100000, 1000000).ToString();
            toastNotification.Tag = toastDoc.GetElementsByTagName("text")[1].InnerText;

            // 将指定的 ScheduledToastNotification 添加进计划列表
            ToastNotifier toastNotifier = ToastNotificationManager.CreateToastNotifier();
            toastNotifier.AddToSchedule(toastNotification);

            ShowScheduledToasts();
        }
        
        // 删除指定的 ScheduledToastNotification 对象
        private void btnRemoveScheduledToast_Click(object sender, RoutedEventArgs e)
        {
            string notificationId = (string)(sender as FrameworkElement).Tag;

            // 获取当前 app 的全部 ScheduledToastNotification 对象列表
            ToastNotifier toastNotifier = ToastNotificationManager.CreateToastNotifier();
            IReadOnlyList<ScheduledToastNotification> notifications = toastNotifier.GetScheduledToastNotifications();

            int notificationCount = notifications.Count;
            for (int i = 0; i < notificationCount; i++)
            {
                if (notifications[i].Id == notificationId)
                {
                    // 从计划列表中移除指定的 ScheduledToastNotification 对象
                    toastNotifier.RemoveFromSchedule(notifications[i]);
                    break;
                }
            }

            ShowScheduledToasts();
        }

        // 显示当前 app 的全部 ScheduledToastNotification 列表
        private void ShowScheduledToasts()
        {
            // 获取当前 app 的全部 ScheduledToastNotification 对象列表
            ToastNotifier toastNotifier = ToastNotificationManager.CreateToastNotifier();
            IReadOnlyList<ScheduledToastNotification> notifications = toastNotifier.GetScheduledToastNotifications();

            listBox.ItemsSource = notifications;
        }
    }
}



OK
[源码下载]