本文將告訴大家如何在 WPF 不安裝 WindowsAppSDK 包,且不在 TargetFramework 帶上 TargetPlatformVersion 而彈出 Win10 的 Toast 通知的方法
本文這裡的 TargetPlatformVersion 指的是在 TargetFramework 裡面的內容,如下面的程式碼裡的 10.0.17763.0 就是 TargetPlatformVersion 的值
<PropertyGroup>
<TargetFramework>net9.0-windows10.0.17763.0</TargetFramework>
</PropertyGroup>
不帶 TargetPlatformVersion 即不在 TargetFramework 里加上 10.0.x 的版本號
預設微軟官方推薦使用的是千年不更新的 Microsoft.Toolkit.Uwp.Notifications 庫,配合設定了 TargetPlatformVersion 至少為 10.0.17763.0 版本進行 Toast 通知
其預設推薦方法的 csproj 內容大概如下
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>WinExe</OutputType>
<TargetFramework>net9.0-windows10.0.17763.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
<UseWPF>true</UseWPF>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Toolkit.Uwp.Notifications" Version="7.1.3" />
</ItemGroup>
</Project>
此方式需要引用 Microsoft.Toolkit.Uwp.Notifications 且在 TargetFramework 里加上 10.0.17763.0 版本。其使用方法非常簡單,如下面程式碼即可彈出文字
var builder = new ToastContentBuilder()
.AddText("林德熙是逗比")
;
builder.Show();
然而以上方法我感覺不夠清真。接下來來將告訴大家一個我感覺比較清真的方法
使用 WPF 不安裝 WindowsAppSDK 使用 WinRT 功能的方法 這篇部落格提到的方法,即可不用指定 TargetPlatformVersion 就可以使用 WinRT 的功能
正好 Toast 就是 WinRT 的功能
具體的做法是先取出 Microsoft.Windows.SDK.NET.dll 和 WinRT.Runtime.dll 兩個檔案作為引用,我這裡放在了我的 C:\lindexi\Library
資料夾裡,修改 csproj 引用這兩個檔案,修改之後的 csproj 檔案程式碼如下
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>WinExe</OutputType>
<TargetFramework>net9.0-windows</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
<UseWPF>true</UseWPF>
</PropertyGroup>
<ItemGroup>
<Reference Include="Microsoft.Windows.SDK.NET">
<HintPath>C:\lindexi\Library\Microsoft.Windows.SDK.NET.dll</HintPath>
</Reference>
<Reference Include="WinRT.Runtime">
<HintPath>C:\lindexi\Library\WinRT.Runtime.dll</HintPath>
</Reference>
</ItemGroup>
</Project>
如此可以看到 csproj 不需要加上 TargetPlatformVersion 的引用,也沒有 WindowsAppSDK 的引用。看起來清真
完成以上程式碼之後,我在 MainWindow 的 Loaded 事件嘗試彈出通知內容。先根據 https://learn.microsoft.com/en-us/windows/apps/design/shell/tiles-and-notifications/adaptive-interactive-toasts?tabs=xml 文件構建出 XML 程式碼,我這裡的例子程式碼只顯示一行文字
<toast>
<visual>
<binding template='ToastText01'>
<text id="1">顯示文字內容</text>
</binding>
</visual>
</toast>
完成構建 XML 程式碼之後,需要轉換為 XmlDocument 物件,程式碼如下
var xmlDocument = new XmlDocument();
// lang=xml
var toast = """
<toast>
<visual>
<binding template='ToastText01'>
<text id="1">顯示文字內容</text>
</binding>
</visual>
</toast>
""";
xmlDocument.LoadXml(xml: toast);
使用 XML 直接寫比較適合簡單的業務,可以看到以上的程式碼十分簡單
除了直接編寫 XML 之外,還可以使用模版輔助,如下面程式碼,在 ToastNotificationManager 裡面獲取模版,然後在模版裡面新增內容
xmlDocument = ToastNotificationManager.GetTemplateContent(ToastTemplateType.ToastText01);
XmlNodeList stringElements = xmlDocument.GetElementsByTagName("text");
stringElements[0].AppendChild(xmlDocument.CreateTextNode("顯示文字內容"));
以上這兩個方式的效果都是差不多的,大家可以選自己喜歡的方式
完成基礎配置之後,接下來使用 ToastNotificationManager 將通知彈出,程式碼如下
var toastNotification = new ToastNotification(xmlDocument);
var toastNotificationManagerForUser = ToastNotificationManager.GetDefault();
var toastNotifier = toastNotificationManagerForUser.CreateToastNotifier(applicationId: "應用名");
toastNotifier.Show(toastNotification);
以上程式碼有一個細節是 CreateToastNotifier 需要傳入應用名,如果沒有傳入將炸異常,這是微軟設計問題
最後別忘記了在開始呼叫 WinRT 之前,使用 ComWrappersSupport 進行初始化
global::WinRT.ComWrappersSupport.InitializeComWrappers();
完成之後的程式碼如下
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
Loaded += MainWindow_Loaded;
}
private void MainWindow_Loaded(object sender, RoutedEventArgs e)
{
if (OperatingSystem.IsWindowsVersionAtLeast(10, 0, 15063))
{
global::WinRT.ComWrappersSupport.InitializeComWrappers();
// 以下 XML 的構建,請看
// https://learn.microsoft.com/en-us/windows/apps/design/shell/tiles-and-notifications/adaptive-interactive-toasts?tabs=xml
var xmlDocument = new XmlDocument();
// lang=xml
var toast = """
<toast>
<visual>
<binding template='ToastText01'>
<text id="1">顯示文字內容</text>
</binding>
</visual>
</toast>
""";
xmlDocument.LoadXml(xml: toast);
var toastNotification = new ToastNotification(xmlDocument);
var toastNotificationManagerForUser = ToastNotificationManager.GetDefault();
var toastNotifier = toastNotificationManagerForUser.CreateToastNotifier(applicationId: "應用名");
toastNotifier.Show(toastNotification);
}
}
}
嘗試執行以上程式碼,就可以看到在視窗載入之後,彈出一條通知訊息
本文程式碼放在 github 和 gitee 上,可以使用如下命令列拉取程式碼。我整個程式碼倉庫比較龐大,使用以下命令列可以進行部分拉取,拉取速度比較快
先建立一個空資料夾,接著使用命令列 cd 命令進入此空資料夾,在命令列裡面輸入以下程式碼,即可獲取到本文的程式碼
git init
git remote add origin https://gitee.com/lindexi/lindexi_gd.git
git pull origin ffad2f4c67a9e53fb9121f5d807191a5a913098d
以上使用的是國內的 gitee 的源,如果 gitee 不能訪問,請替換為 github 的源。請在命令列繼續輸入以下程式碼,將 gitee 源換成 github 源進行拉取程式碼。如果依然拉取不到程式碼,可以發郵件向我要程式碼
git remote remove origin
git remote add origin https://github.com/lindexi/lindexi_gd.git
git pull origin ffad2f4c67a9e53fb9121f5d807191a5a913098d
獲取程式碼之後,進入 WPFDemo/LenukelbawChejeabecacar/HeregemdibeHeaqereweganilai 資料夾,即可獲取到原始碼
更多技術部落格,請參閱 部落格導航