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

应用通知是应用可以构造和传送给用户的消息,而用户当前不在你的应用中。

应用通知的屏幕截图

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

Note

术语“toast 通知”将替换为“应用通知”。 这些术语都指的是 Windows 的相同功能,但随着时间的推移,我们将逐步取消在文档中使用“toast 通知”。

Important

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

步骤 1:安装 NuGet 包

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

Important

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

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

.NET 应用程序必须使用其中一个 Windows TFM,否则将缺少应用程序通知发送和管理 API,例如Show()。 将 TFM 设置为 net6.0-windows10.0.17763.0 及以上版本。

我们的代码示例将使用此包。 此包允许你在不使用 XML 的情况下创建应用通知,并允许桌面应用发送应用通知。

步骤 2:发送应用通知

在 Windows 10 和 Windows 11 中,应用通知内容是使用自适应语言描述的,该语言允许你对通知的外观具有极大的灵活性。 有关详细信息,请参阅 应用通知内容 文档。

我们将从简单的基于文本的通知开始。 构造通知内容(使用通知库),并显示通知! 请注意,命名空间 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 和打包和解压缩的桌面应用而异。

首先,在 Package.appxmanifest中添加:

  1. xmlns:com 声明
  2. xmlns:desktop 声明
  3. IgnorableNamespaces 属性中,comdesktop
  4. 桌面:扩展 for windows.toastNotificationActivation 声明为 toast 激活器的 CLSID(使用所选的新 GUID)。
  5. 仅限 MSIX:使用步骤 4 中的 GUID 为 COM 激活器定义 com:Extension。 请务必包含 Arguments="-ToastActivated",以便您可以确认您的启动源于通知。

Package.appxmanifest

<!--Add these namespaces-->
<Package
  ...
  xmlns:com="http://schemas.microsoft.com/appx/manifest/com/windows10"
  xmlns:desktop="http://schemas.microsoft.com/appx/manifest/desktop/windows10"
  IgnorableNamespaces="... com desktop">
  ...
  <Applications>
    <Application>
      ...
      <Extensions>

        <!--Specify which CLSID to activate when toast clicked-->
        <desktop:Extension Category="windows.toastNotificationActivation">
          <desktop:ToastNotificationActivation ToastActivatorCLSID="replaced-with-your-guid-C173E6ADF0C3" /> 
        </desktop:Extension>

        <!--Register COM CLSID LocalServer32 registry key-->
        <com:Extension Category="windows.comServer">
          <com:ComServer>
            <com:ExeServer Executable="YourProject\YourProject.exe" Arguments="-ToastActivated" DisplayName="Toast activator">
              <com:Class Id="replaced-with-your-guid-C173E6ADF0C3" DisplayName="Toast activator"/>
            </com:ExeServer>
          </com:ComServer>
        </com:Extension>

      </Extensions>
    </Application>
  </Applications>
 </Package>

然后,在 应用的启动代码(App.xaml.cs 的 OnStartup 中用于 WPF),添加对 OnActivated 事件的订阅。

// Listen to notification activation
ToastNotificationManagerCompat.OnActivated += toastArgs =>
{
    // Obtain the arguments from the notification
    ToastArguments args = ToastArguments.Parse(toastArgs.Argument);

    // Obtain any user input (text boxes, menu selections) from the notification
    ValueSet userInput = toastArgs.UserInput;

    // Need to dispatch to UI thread if performing UI operations
    Application.Current.Dispatcher.Invoke(delegate
    {
        // TODO: Show the corresponding content
        MessageBox.Show("Toast activated. Args: " + toastArgs.Argument);
    });
};

当用户单击任何通知(或通知上的按钮)时,将发生以下情况...

如果应用程序当前正在运行...

  1. ToastNotificationManagerCompat.OnActivated 事件将在后台线程中被调用。

如果应用当前已关闭...

  1. 你的应用程序的 EXE 将被启动,ToastNotificationManagerCompat.WasCurrentProcessToastActivated() 将返回 true,以表明进程是由于现代激活而启动的,并且事件处理程序将很快被调用。
  2. 然后,ToastNotificationManagerCompat.OnActivated 事件将在后台线程中被触发。

步骤 4:处理卸载

你不需要做任何事情! 卸载 MSIX 应用时,会自动清理所有通知和其他任何相关资源。

Add images

你可以向通知添加丰富的内容。 我们将添加内联图像和用户资料(应用程序徽标覆盖)图像。

Note

可以从应用程序包、应用的本地存储或网络中使用图像。 从 Fall Creators Update 开始,普通连接上的 Web 图像最多可以为 3 MB,按流量计费的连接可以达到 1 MB。 在尚未运行 Fall Creators Update 的设备上,Web 图像必须不超过 200 KB。

Important

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

使用图像 的 吐司
// 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();

添加按钮和输入框

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

包含输入和按钮的应用通知的屏幕截图
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();

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

请注意,如果按钮使用上面所示的 AddArgument API,那么在单击按钮时,添加到顶级应用通知中的参数(如对话 ID)也会被返回。但如果在按钮上自定义分配参数,则不会包含这些顶级参数。

处理后台激活

对于桌面应用程序,后台激活的处理方式与前台激活相同(将触发 OnActivated 事件处理程序)。 可以选择不显示任何 UI,并在处理激活后关闭应用。

设置过期时间

在 Windows 10 中,所有应用程序通知在被用户消除或忽略后都会进入操作中心,以便用户在弹出消失后可以查看通知。

但是,如果通知中的消息仅在一段时间内相关,则应在应用通知上设置过期时间,以便用户看不到应用中的过时信息。 例如,如果促销仅有效 12 小时,请将到期时间设置为 12 小时。 在下面的代码中,我们将过期时间设置为 2 天。

Note

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

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

为通知提供主密钥

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

若要查看有关替换/删除已交付的应用通知的更多详细信息,请参阅 快速入门:在作中心(XAML)中管理 Toast 通知

标签和组一起用作复合主键。 组是更通用的标识符,可在其中分配“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. 用户收到有关对话中新消息的多个应用通知。
  2. 用户点击其中一条通知以打开对话。
  3. 应用打开对话,然后通过对话中应用提供的组上的RemoveGroup清除所有通知。
  4. 用户的操作中心现在正确反映通知状态,因为操作中心中没有留下的该会话的过时通知。

若要了解如何清除所有通知或删除特定通知,请参阅 快速入门:在操作中心(XAML)中管理 Toast 通知。

ToastNotificationManagerCompat.History.Clear();

Resources