使用C#封装一个UWP的Toast通知类

简介

在 UWP 开发中,可以使用 Toast 方式直接生成系统通知,并出现在 Windows 的通知中心中。 Toast 通知的核心是一个 XML 文档,其中包含了通知的图标、文字和式样。系统中提供了该 XML 文档的模板。

在这里使用了类似于 jQuery 的连缀操作的形式使用 C#封装了一个关于通知的类,不过还不支持 win10 可交互通知,以后会加入。

模板类型

消息通知的模板一共有 8 中,这里有每一种模板的介绍。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
//
// Summary:
// 指定要在消息通知中使用的模版。
[ContractVersion(typeof(UniversalApiContract), 65536)]
public enum ToastTemplateType
{
//
// Summary:
// 在三行文本中被包装的大型图像和单个字符串。
ToastImageAndText01 = 0,
//
// Summary:
// 大图像、加粗文本的一个字符串在第一行、常规文本的一个字符串包装在第二、三行中。
ToastImageAndText02 = 1,
//
// Summary:
// 大图像、加粗文本的一个字符串被包装在开头两行中、常规文本的一个字符串包装在第三行中。
ToastImageAndText03 = 2,
//
// Summary:
// 大图像、加粗文本的一个字符串在第一行、常规文本的一个字符串在第二行中、常规文本的一个字符串在第三行中。
ToastImageAndText04 = 3,
//
// Summary:
// 包装在三行文本中的单个字符串。
ToastText01 = 4,
//
// Summary:
// 第一行中加粗文本的一个字符串、覆盖第二行和第三行的常规文本的一个字符串。
ToastText02 = 5,
//
// Summary:
// 覆盖第一行和第二行的加粗文本的一个字符串。第三行中常规文本的一个字符串。
ToastText03 = 6,
//
// Summary:
// 第一行中加粗文本的一个字符串、第二行中常规文本的一个字符串、第三行中常规文本的一个字符串。
ToastText04 = 7
}

以下是每一种通知的 XML 模板内容

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
//类型 0
<toast>
<visual>
<binding template="ToastImageAndText01">
<image id="1" src="" />
<text id="1"></text>
</binding>
</visual>
</toast>
//类型 1
<toast>
<visual>
<binding template="ToastImageAndText02">
<image id="1" src="" />
<text id="1"></text>
<text id="2"></text>
</binding>
</visual>
</toast>
//类型 2
<toast>
<visual>
<binding template="ToastImageAndText03">
<image id="1" src="" />
<text id="1"></text>
<text id="2"></text>
</binding>
</visual>
</toast>
//类型 3
<toast>
<visual>
<binding template="ToastImageAndText04">
<image id="1" src="" />
<text id="1"></text>
<text id="2"></text>
<text id="3"></text>
</binding>
</visual>
</toast>
//类型 4
<toast>
<visual>
<binding template="ToastText01">
<text id="1"></text>
</binding>
</visual>
</toast>
//类型 5
<toast>
<visual>
<binding template="ToastText02">
<text id="1"></text>
<text id="2"></text>
</binding>
</visual>
</toast>
//类型 6
<toast>
<visual>
<binding template="ToastText03">
<text id="1"></text>
<text id="2"></text>
</binding>
</visual>
</toast>
//类型 7
<toast>
<visual>
<binding template="ToastText04">
<text id="1"></text>
<text id="2"></text>
<text id="3"></text>
</binding>
</visual>
</toast>

代码实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
using System;
using System.Collections.Generic;
using Windows.Data.Xml.Dom;
using Windows.UI.Notifications;

class ToastLib {

//定义通知模板和XML节点
private ToastTemplateType toastTemplate;
private XmlDocument toastXml;
private IXmlNode toastNode;
private XmlNodeList toastTextElements;
private XmlNodeList toastImageAttributes;

//消息类型
private int toastType;
private int ToastType {
set {
if (value >= 0 && value <= 7) {
toastType = value;
} else {
throw new ArgumentOutOfRangeException();
}
}
get {
return toastType;
}
}

//构造函数,传入通知模板种类即可
public ToastLib(int type = 0) {
ToastType = type;
toastTemplate = (ToastTemplateType)ToastType;
toastXml = ToastNotificationManager.GetTemplateContent(toastTemplate);
toastTextElements = toastXml.GetElementsByTagName("text");
toastImageAttributes = toastXml.GetElementsByTagName("image");
}

//生成通知XML的关键函数,用于传入通知图片的连接和通知文字的内容
//传入字符串sample "消息内容" or $"ms-appx:///assets/图片文件名"
public ToastLib makeToast(List<string> toastPara) {
int[] toastParaNumArr = { 2, 3, 3, 4, 1, 2, 2, 3 };
if (toastPara.Count == toastParaNumArr[ToastType]) {
switch (ToastType) {
case 0:
toastTextElements[0].AppendChild(toastXml.CreateTextNode(toastPara[0]));
((XmlElement)toastImageAttributes[0]).SetAttribute("src", toastPara[1]);
((XmlElement)toastImageAttributes[0]).SetAttribute("alt", "logo");
break;
case 1:
((XmlElement)toastImageAttributes[0]).SetAttribute("src", toastPara[0]);
((XmlElement)toastImageAttributes[0]).SetAttribute("alt", "logo");
toastTextElements[0].AppendChild(toastXml.CreateTextNode(toastPara[1]));
toastTextElements[1].AppendChild(toastXml.CreateTextNode(toastPara[2]));
break;
case 2:
((XmlElement)toastImageAttributes[0]).SetAttribute("src", toastPara[0]);
((XmlElement)toastImageAttributes[0]).SetAttribute("alt", "logo");
toastTextElements[0].AppendChild(toastXml.CreateTextNode(toastPara[1]));
toastTextElements[1].AppendChild(toastXml.CreateTextNode(toastPara[2]));
break;
case 3:
((XmlElement)toastImageAttributes[0]).SetAttribute("src", toastPara[0]);
((XmlElement)toastImageAttributes[0]).SetAttribute("alt", "logo");
toastTextElements[0].AppendChild(toastXml.CreateTextNode(toastPara[1]));
toastTextElements[1].AppendChild(toastXml.CreateTextNode(toastPara[2]));
toastTextElements[2].AppendChild(toastXml.CreateTextNode(toastPara[3]));
break;
case 4:
toastTextElements[0].AppendChild(toastXml.CreateTextNode(toastPara[0]));
break;
case 5:
toastTextElements[0].AppendChild(toastXml.CreateTextNode(toastPara[0]));
toastTextElements[1].AppendChild(toastXml.CreateTextNode(toastPara[1]));
break;
case 6:
toastTextElements[0].AppendChild(toastXml.CreateTextNode(toastPara[0]));
toastTextElements[1].AppendChild(toastXml.CreateTextNode(toastPara[1]));
break;
case 7:
toastTextElements[0].AppendChild(toastXml.CreateTextNode(toastPara[0]));
toastTextElements[1].AppendChild(toastXml.CreateTextNode(toastPara[1]));
toastTextElements[2].AppendChild(toastXml.CreateTextNode(toastPara[2]));
break;
}
} else {
throw new ArgumentException();
}
return this;
}

//加入点按通知进入App以后向App传入的参数
//para example "{"type":"toast","param1":"12345","param2":"67890"}"
public ToastLib addToastLaunchPara(string launchPara) {
((XmlElement)toastNode).SetAttribute("launch", launchPara);
return this;
}

//改变通知的声音
//the avaliable tones are here:Default,IM,Mail,Reminder,SMS,Looping.Alarm,Looping.Alarm2,Looping.Alarm3,Looping.Alarm4,Looping.Alarm5,Looping.Alarm6,Looping.Alarm7,Looping.Alarm8,Looping.Alarm9,Looping.Alarm10,Looping.Call,Looping.Call2,Looping.Call3,Looping.Call4,Looping.Call5,Looping.Call6,Looping.Call7,Looping.Call8,Looping.Call9,Looping.Call10
public ToastLib setToastTone(string tone) {
XmlElement audio = toastXml.CreateElement("audio");
audio.SetAttribute("src", $"ms-winsoundevent:Notification." + tone);
toastNode.AppendChild(audio);
return this;
}

//改变通知的时长
//only 2 types of paras short or long
public ToastLib setToastDuringTime(string duringTime) {
((XmlElement)toastNode).SetAttribute("duration", duringTime);
return this;
}

//显示通知
public void showToast() {
ToastNotification toast = new ToastNotification(toastXml);
ToastNotificationManager.CreateToastNotifier().Show(toast);
}

}

使用方式

使用方式非常简单,类似于 jQuery 的连缀操作,可以有选择地对通知进行定制。

1
2
3
4
5
6
7
8
9
10
11
12
public void toastInfo(string info) {
//默认使用第 0 个模板,如果构造时候传入其他参数则可以使用其他模板
ToastLib toastLib = new ToastLib();
//需要将要传入 makeToast 的字符串写入一个 List 中
List<string> toastStrs = new List<string>();
toastStrs.Add(info);
toastStrs.Add("there's no logo :(");
//最简单的 toast,其余参数均使用默认
toastLib.makeToast(toastStrs).showToast();
//使用连缀操作进行 toast 定制化设置,最终调用 showToast()进行展示,具体参数可以参考对于每一个函数的注释
toastLib.makeToast(toastStrs).setToastTone("IM").setToastDuringTime("long").showToast();
}

获取文中代码

在 GitHub 的 HelloBUPT 项目中可以得到代码:https://github.com/imaginezz/helloBUPT/blob/master/beiyou/CommonLibrary/ToastLib.cs

参考链接

Windows 10 UWP 开发:如何弹出消息通知:http://edi.wang/post/2015/11/8/uwp-toast-notification?utm_source=tuicool&utm_medium=referral

自适应和交互式 Toast 通知:https://msdn.microsoft.com/zh-cn/windows/uwp/controls-and-patterns/tiles-and-notifications-adaptive-interactive-toasts

使用 Nuget 包发送本地通知:https://msdn.microsoft.com/windows/uwp/controls-and-patterns/tiles-and-notifications-sending-a-local-tile-notification

ToastNotification Class:https://msdn.microsoft.com/zh-cn/library/windows/apps/windows.ui.notifications.toastnotification.aspx