从 C# 应用发送本地 Toast 通知

toast 通知是用户当前未在应用内部时可由应用构造并发送给用户的消息。

Toast 通知的屏幕截图

本快速入门将引导你完成使用丰富内容和交互式操作创建、交付和显示Windows 10或Windows 11 Toast 通知的步骤。 本快速入门使用本地通知,这是要实现的最简单通知。 所有类型的应用(WPF、UWP、WinForms、控制台)都可以发送通知!

重要

如果要编写 C++ 应用,请参阅 C++ UWPC++ WRL 文档。

步骤 1:安装 NuGet 包

在 Visual Studio 解决方案中,右键单击项目,单击“管理 NuGet 包...”,然后搜索并安装 Microsoft.Toolkit.Uwp.NotificationsNuGet 包版本 7.0 或更高版本。

重要

.NET Framework仍使用 packages.config 的桌面应用必须迁移到 PackageReference,否则将无法正确引用 Windows SDK。 在项目中,右键单击“引用”,然后单击“将 packages.config 迁移到 PackageReference”。

.NET Core 3.0 WPF 应用必须更新到 .NET Core 3.1,否则 API 将不存在。

.NET 应用必须使用 其中一个 Windows TPM,否则将缺少 toast 发送和管理 API,例如 Show() 。 将 TFM 设置为 net6.0-windows10.0.17763.0 或更高版本。

代码示例将使用此包。 通过此包,无需使用 XML 即可创建 toast 通知,还允许桌面应用发送 toast。

步骤 2:发送 toast

在Windows 10和Windows 11中,你的 Toast 通知内容使用自适应语言进行描述,该语言可以非常灵活地显示通知的外观。 有关详细信息,请参阅 toast 内容文档

我们将从基于文本的简单通知开始。 构造通知内容(使用通知库),然后显示通知! 请注意,命名空间为 Microsoft.Toolkit.Uwp.Notifications

简单文本通知
// Requires Microsoft.Toolkit.Uwp.Notifications NuGet package version 7.0 or greater
new ToastContentBuilder()
    .AddArgument("action", "viewConversation")
    .AddArgument("conversationId", 9813)
    .AddText("Andrew sent you a picture")
    .AddText("Check this out, The Enchantments in Washington!")
    .Show(); // Not seeing the Show() method? Make sure you have version 7.0, and if you're using .NET 6 (or later), then your TFM must be net6.0-windows10.0.17763.0 or greater

尝试运行此代码,应会看到通知出现!

步骤 3:处理激活

显示通知后,可能需要处理用户单击通知事件(这意味着在用户单击该通知后显示特定内容、一般情况下打开应用,还是在用户单击通知时执行操作)。

处理 UWP 和打包和未打包桌面应用的激活步骤有所不同。

当用户单击通知(或具有前台激活的通知上的按钮),将调用应用的 App.xaml.csOnActivated,并返回添加的参数。

App.xaml.cs

protected override void OnActivated(IActivatedEventArgs e)
{
    // Handle notification activation
    if (e is ToastNotificationActivatedEventArgs toastActivationArgs)
    {
        // Obtain the arguments from the notification
        ToastArguments args = ToastArguments.Parse(toastActivationArgs.Argument);

        // Obtain any user input (text boxes, menu selections) from the notification
        ValueSet userInput = toastActivationArgs.UserInput;
 
        // TODO: Show the corresponding content
    }
}

重要

必须按 OnLaunched 代码那样初始化框架和激活窗口。 如果用户单击你的 toast ,则不会调用 OnLaunched,即使你的应用已关闭并是首次启动也是如此。 通常建议将 OnLaunchedOnActivated 合并到你自己的 OnLaunchedOrActivated 方法中,因为二者中均需执行相同的初始化。

步骤 4:处理卸载

无需执行任何操作! 卸载 UWP 应用时,会自动清理所有通知和其他任何相关资源。

添加图像

可以将丰富的内容添加到通知。 我们将添加内联图像和配置文件(应用徽标替代)图像。

注意

图像可来自于应用包、应用的本地存储或来自 Web。 自 Fall Creators Update 起,正常连接上的 Web 图像的大小限制提升至 3 MB,按流量计费的连接上的限制提升至 1 MB。 在尚未运行 Fall Creators Update 的设备上,Web 图像的大小不得超过 200 KB。

重要

只有清单中具有 Internet 功能的打包应用才支持 Http 映像。 未打包的应用不支持 http 映像;必须将映像下载到本地应用数据,并在本地引用它。

带图像的 Toast
// Construct the content and show the toast!
new ToastContentBuilder()
    ...

    // Inline image
    .AddInlineImage(new Uri("https://picsum.photos/360/202?image=883"))

    // Profile (app logo override) image
    .AddAppLogoOverride(new Uri("ms-appdata:///local/Andrew.jpg"), ToastGenericAppLogoCrop.Circle)
    
    .Show();

添加按钮和输入

可以添加按钮和输入,使通知具有交互性。 按钮可以启动前台应用、协议或后台任务。 我们将添加一个回复文本框、一个“赞”按钮和一个打开图像的“查看”按钮。

包含输入和按钮的 Toast 通知的屏幕截图
int conversationId = 384928;

// Construct the content
new ToastContentBuilder()
    .AddArgument("conversationId", conversationId)
    ...

    // Text box for replying
    .AddInputTextBox("tbReply", placeHolderContent: "Type a response")

    // Buttons
    .AddButton(new ToastButton()
        .SetContent("Reply")
        .AddArgument("action", "reply")
        .SetBackgroundActivation())

    .AddButton(new ToastButton()
        .SetContent("Like")
        .AddArgument("action", "like")
        .SetBackgroundActivation())

    .AddButton(new ToastButton()
        .SetContent("View")
        .AddArgument("action", "viewImage")
        .AddArgument("imageUrl", image.ToString()))
    
    .Show();

前台按钮的激活处理方式与主 toast 正文相同(将调用 App.xaml.cs OnActivated)。

请注意,单击按钮时,添加到顶级 toast 的参数(例如对话 ID)也将返回,只要按钮使用如上所示的 AddArgument API(如果在按钮上自定义分配参数,则顶级参数不会包含在内)。

处理后台激活

当你对你的 toast(或 toast 内的按钮)指定后台激活时,将执行后台任务而不是激活前台应用。

有关后台任务的详细信息,请参阅使用后台任务支持应用

如果面向内部版本 14393 或更高版本,则可以使用进程内后台任务,这极大地简化了操作。 请注意,无法在较旧版本的 Windows 上运行进程内后台任务。 在此代码示例中,将使用进程内后台任务。

const string taskName = "ToastBackgroundTask";

// If background task is already registered, do nothing
if (BackgroundTaskRegistration.AllTasks.Any(i => i.Value.Name.Equals(taskName)))
    return;

// Otherwise request access
BackgroundAccessStatus status = await BackgroundExecutionManager.RequestAccessAsync();

// Create the background task
BackgroundTaskBuilder builder = new BackgroundTaskBuilder()
{
    Name = taskName
};

// Assign the toast action trigger
builder.SetTrigger(new ToastNotificationActionTrigger());

// And register the task
BackgroundTaskRegistration registration = builder.Register();

然后,在 App.xaml.cs 中重写 OnBackgroundActivated 方法。 接下来可以检索预定义的参数和用户输入,类似于前台激活。

App.xaml.cs

protected override async void OnBackgroundActivated(BackgroundActivatedEventArgs args)
{
    var deferral = args.TaskInstance.GetDeferral();
 
    switch (args.TaskInstance.Task.Name)
    {
        case "ToastBackgroundTask":
            var details = args.TaskInstance.TriggerDetails as ToastNotificationActionTriggerDetail;
            if (details != null)
            {
                ToastArguments arguments = ToastArguments.Parse(details.Argument);
                var userInput = details.UserInput;

                // Perform tasks
            }
            break;
    }
 
    deferral.Complete();
}

设置过期时间

在 Windows 10 中,所有 toast 通知被用户消除或忽略后将转到操作中心,以便在弹出窗口消失后,用户仍可查看通知。

但是,如果你的通知中的消息仅在一段时间内相关,则应对 toast 通知设置过期时间,让用户不至于看到来自应用的过时信息。 例如,如果升级的有效时间仅为 12 个小时,则将过期时间设置为 12 个小时。 下面的代码中将过期时间设置为 2 天。

注意

本地 toast 通知的默认和最长过期时间为 3 天。

// Create toast content and show the toast!
new ToastContentBuilder()
    .AddText("Expires in 2 days...")
    .Show(toast =>
    {
        toast.ExpirationTime = DateTime.Now.AddDays(2);
    });

为 toast 提供主键

如要以编程方式删除或替换发送的通知,需使用 Tag 属性(还可选择使用 Group 属性)来为通知提供主键。 然后,你可以在以后使用此主键来删除或替换该通知。

要查看有关替换/删除已发送的 toast 通知的更多详细信息,请参阅快速入门:在操作中心 (XAML) 中管理 toast 通知

Tag 和 Group 组合充当复合主键。 Group 是两者中较为通用的标识符,你可以用它来分配如“wallPosts”、“messages”、“friendRequests”等组。而 Tag 应该唯一标识组中的通知本身。 使用通用组时,可以使用 RemoveGroup API 删除该组中的所有通知。

// Create toast content and show the toast!
new ToastContentBuilder()
    .AddText("New post on your wall!")
    .Show(toast =>
    {
        toast.Tag = "18365";
        toast.Group = "wallPosts";
    });

清除你的通知

应用负责删除和清除它们自己的通知。 当你的应用启动时,我们不会自动清除你的通知。

仅当用户显式单击通知时,Windows 才会自动删除该通知。

下面是消息传递应用应执行的操作的示例...

  1. 用户收到关于对话中新消息的多个 toast
  2. 用户点击其中一个 toast 以打开该对话
  3. 应用打开该对话,然后清除该对话的所有 toast(方法是对该对话的应用提供的组使用 RemoveGroup
  4. 用户的操作中心现在能正确反映通知状态,因为操作中心未留有该对话的过期通知。

若要了解有关清除所有通知或删除特定通知的信息,请参阅快速入门:在操作中心 (XAML) 中管理 toast 通知

ToastNotificationManagerCompat.History.Clear();

资源