從 UWP 移轉至 WinUI 3 的應用程式通知

將應用程式通知程式代碼從 UWP 移轉至 WinUI 3 時,唯一的差異在於處理通知的啟用。 發送和管理應用程式通知保持完全相同。

注意

「快顯通知」一詞正取代為「應用程式通知」。 這些詞彙都是指 Windows 的相同功能,但隨著時間推移,我們將逐步淘汰文件中的「快顯通知」使用。

注意

針對發行前產品的部分相關資訊,在產品正式發行時可能會有大幅修改。 Microsoft 對此處提供的資訊,不做任何明確或隱含的瑕疵擔保。

啟用差異

類別 UWP WinUI 3
前景啟用進入點 App.xaml.cs 裡面的 OnActivated 方法被叫用 App.xaml.cs 裡面的 OnLaunched 方法被叫用。
背景啟用進入點 以背景工作個別處理 與前景啟動相同。 App.xaml.cs 裡面的 OnLaunched 方法被叫用。 使用 GetActivatedEventArgs 來判斷應用程式是否應該完全啟動,或只處理工作並結束。
視窗啟動 發生前景啟用時,系統會自動將視窗帶入前景 如有需要,您必須將視窗帶到前景

C# 應用程式的移轉

步驟 1:安裝 NuGet 連結庫

針對 WinUI 3 應用程式,您可以使用 AppNotificationManager 類別處理通知的啟用。 此類別是由 Microsoft.WindowsAppSDK Nuget 套件提供,預設包含在 WinUI 3 Visual Studio 專案範本中。

第 2 步:更新清單

在您的 Package.appxmanifest 中,新增:

  1. xmlns:com 宣告
  2. xmlns:desktop 宣告
  3. IgnorableNamespaces 屬性中,comdesktop
  4. windows.toastNotificationActivationdesktop:Extension,用於聲明您的 Toast 啟動器 CLSID (使用您選擇的新 GUID)。
  5. 僅限 MSIX:COM 啟動器的 com:Extension,使用步驟 #4 中的 GUID。 請務必包含 Arguments="----AppNotificationActivated:",以便您知道您的啟動是透過通知進行的
<!--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 app notification 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.exe" Arguments="----AppNotificationActivated:" DisplayName="App notification activator">
              <com:Class Id="replaced-with-your-guid-C173E6ADF0C3" DisplayName="App notification activator"/>
            </com:ExeServer>
          </com:ComServer>
        </com:Extension>

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

步驟 3:處理啟用

在套用的啟動程式碼 (通常為 App.xaml.cs) 中,使用下列步驟更新程式碼:

  1. OnLaunched 中,取得 AppNotificationManager 類別的預設執行個體。
  2. 註冊 AppNotificationManager.NotificationInvoked 事件。
  3. 呼叫 Microsoft.Windows.AppNotifications.AppNotificationManager.Register 註冊您的應用程式以接收通知事件。 註冊 NotificationInvoked 處理程序之後,請務必呼叫這個方法。
  4. 將視窗啟動/啟動程式碼重構為專用的 LaunchAndBringToForegroundIfNeeded 協助程式方法,以便您可以從多個位置呼叫它。
  5. 建立 HandleNotification 協助程式方法,以便從多個位置呼叫它。
  6. 呼叫 AppInstance.GetActivatedEventArgs,並檢查所傳回物件的 AppActivationArguments.Kind 屬性,以取得 ExtendedActivationKind.AppNotification 值。
  7. 如果啟用種類不是 AppNotification,請呼叫 LaunchAndBringToForegroundIfNeeded 協助程式方法。
  8. 如果啟用種類為 AppNotification ,會將 AppActivationArguments.Data 屬性 轉換成 AppNotificationActivatedEventArgs ,並將其傳遞至 HandleNotification 協助程式方法。
  9. 在您的 ApplicationManager.NotificationInvoked 處理程式中,呼叫 HandleNotification 協助程式方法。
  10. HandleNotification 協助程式方法內,在執行任何 UI 相關程式代碼之前,請務必先分派至應用程式或窗口發送器,例如顯示視窗或更新 UI
  11. 將處理應用程式通知啟用的舊 UWP OnActivated 程式代碼移轉至新的HandleNotification協助程式方法。

已移轉的 App.xaml.cs


protected override void OnLaunched(Microsoft.UI.Xaml.LaunchActivatedEventArgs args)
{
    m_window = new MainWindow();

    // To ensure all Notification handling happens in this process instance, register for
    // NotificationInvoked before calling Register(). Without this a new process will
    // be launched to handle the notification.
    AppNotificationManager notificationManager = AppNotificationManager.Default;
    notificationManager.NotificationInvoked += NotificationManager_NotificationInvoked;
    notificationManager.Register();

    var activatedArgs = Microsoft.Windows.AppLifecycle.AppInstance.GetCurrent().GetActivatedEventArgs();
    var activationKind = activatedArgs.Kind;
    if (activationKind != ExtendedActivationKind.AppNotification)
    {
        LaunchAndBringToForegroundIfNeeded();
    } else
    {
        HandleNotification((AppNotificationActivatedEventArgs)activatedArgs.Data);
    }

}

private void LaunchAndBringToForegroundIfNeeded()
{
    if (m_window == null)
    {
        m_window = new MainWindow();
        m_window.Activate();

        // Additionally we show using our helper, since if activated via a app notification, it doesn't
        // activate the window correctly
        WindowHelper.ShowWindow(m_window);
    }
    else
    {
        WindowHelper.ShowWindow(m_window);
    }
}

private void NotificationManager_NotificationInvoked(AppNotificationManager sender, AppNotificationActivatedEventArgs args)
{
    HandleNotification(args);
}

private void HandleNotification(AppNotificationActivatedEventArgs args)
{
  // Use the dispatcher from the window if present, otherwise the app dispatcher
  var dispatcherQueue = m_window?.DispatcherQueue ?? DispatcherQueue.GetForCurrentThread();


  dispatcherQueue.TryEnqueue(async delegate
  {

      switch (args.Arguments["action"])
      {
          // Send a background message
          case "sendMessage":
              string message = args.UserInput["textBox"].ToString();
              // TODO: Send it

              // If the UI app isn't open
              if (m_window == null)
              {
                  // Close since we're done
                  Process.GetCurrentProcess().Kill();
              }

              break;

          // View a message
          case "viewMessage":

              // Launch/bring window to foreground
              LaunchAndBringToForegroundIfNeeded();

              // TODO: Open the message
              break;
      }
  });
}

private static class WindowHelper
{
    [DllImport("user32.dll")]
    private static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);

    [DllImport("user32.dll")]
    [return: MarshalAs(UnmanagedType.Bool)]
    private static extern bool SetForegroundWindow(IntPtr hWnd);

    public static void ShowWindow(Window window)
    {
        // Bring the window to the foreground... first get the window handle...
        var hwnd = WinRT.Interop.WindowNative.GetWindowHandle(window);

        // Restore window if minimized... requires DLL import above
        ShowWindow(hwnd, 0x00000009);

        // And call SetForegroundWindow... requires DLL import above
        SetForegroundWindow(hwnd);
    }
}

建置應用程式通知內容

使用 Windows 應用程式 SDK,您仍然可以使用原始 xml 建立應用程式通知內容,但您也可以使用新的 AppNotificationsBuilder API 建立應用程式通知內容,該 API 取代了 Windows 社群工具包提供的 ToastContentBuilder 類別。 呼叫 AppNotificationManager.Show 來傳送應用程式通知。 不建議混合 Windows Community Toolkit 和 App SDK API。

using Microsoft.Windows.AppNotifications;
using Microsoft.Windows.AppNotifications.Builder;

...

var builder = new AppNotificationBuilder()
    .AddText("Send a message.")
    .AddTextBox("textBox")
    .AddButton(new AppNotificationButton("Send")
        .AddArgument("action", "sendMessage"));

var notificationManager = AppNotificationManager.Default;
notificationManager.Show(builder.BuildNotification());