C# WPF ToastNotifications贪睡后无法区分激活事件类型问题
贪睡流程触发后,重新弹出的通知由Windows通知平台自动调度生成,并非代码中手动调用ShowNotification()创建的通知实例,因此手动给该实例绑定的Activated/Dismissed/Failed事件处理器对重弹通知完全无效。同时你将Now按钮的激活类型设置为background,且未注册全局Toast激活监听,因此应用被通知激活时,启动参数只会携带通用的-ToastActivated -Embedding标记,无法获取具体触发源信息。
按照以下步骤调整即可覆盖首次弹出、贪睡重弹、应用未运行时点击通知的所有交互场景:
- 第一步:为所有可交互的通知元素配置唯一标识参数
目前你仅给Now按钮配置了参数,可点击的"IMPORTANT"文本未配置激活参数,同时自定义参数不要使用无意义占位符,直接使用明确的键值对即可。修改后的通知XML参考如下:
protected override void OnStartup(StartupEventArgs sea)
{
// 注册全局Toast激活监听,所有通知激活场景都会触发该事件
ToastNotificationManagerCompat.OnActivated += ToastActivatedHandler;
// 原有启动参数逻辑 if (sea.Args.Count() > 0) { String s = "args:"; foreach (var item in sea.Args) s = s + "<" + item + ">"; if (sea.Args[0] == "RKToast.xml") { ShowNotification(); } // 原有-ToastActivated分支无需单独处理,全局事件会自动捕获完整激活参数 } base.OnStartup(sea);
}
// 全局激活处理逻辑
private void ToastActivatedHandler(ToastNotificationActivatedEventArgsCompat e)
{
// 解析XML中配置的自定义参数,贪睡重弹的通知也能正常拿到
ToastArguments args = ToastArguments.Parse(e.Argument);
// 获取通知上的用户输入(比如贪睡时长选择值)
var userInput = e.UserInput;
// 切换到UI线程执行业务逻辑 Dispatcher.Invoke(() => { switch (args.Get("action")) { case "executeNow": // 写入Now按钮的点击处理逻辑 MessageBox.Show("触发Now按钮点击"); break; case "clickImportant": // 写入IMPORTANT文本的点击处理逻辑 MessageBox.Show("触发Important文本点击"); break; } });
}
- 第三步:调整`ShowNotification`方法的事件绑定 全局监听已经覆盖所有激活场景,无需再给单个通知实例绑定`Activated`事件,仅保留关闭、失败事件即可: ```csharp void ShowNotification() { // 原有构造xmlDocument的逻辑保持不变 notification = new ToastNotification(xmlDocument); notification.Dismissed += ToastDismissed; notification.Failed += ToastFailed; ToastNotificationManagerCompat.CreateToastNotifier().Show(notification); }
注意:WPF桌面应用使用Toast通知时,自定义交互元素的
activationType统一设为foreground即可,不要设为background后又不配置对应的后台任务,否则会出现激活参数丢失、事件不触发的问题。全局监听方案不需要手动解析启动参数字符串,事件参数会携带完整的激活上下文,兼容所有通知弹出场景。
内容的提问来源于stack exchange,提问作者rgry

