C#或Winform中的消息通知之系统本地通知(local toast notification)

简介: C#应用通过 Microsoft.Toolkit.Uwp.Notifications NuGet包可以很方便的发送本地通知,适用于所有类型的应用(WPF、UWP、WinForms、控制台)

C#应用通过 Microsoft.Toolkit.Uwp.Notifications NuGet包可以很方便的发送本地通知(Windows 10或Windows 11 的 Toast 通知,之前系统版本未提供此类通知),适用于所有类型的应用(WPF、UWP、WinForms、控制台【实际使用各自有着不同限制】)。

后面会介绍使用任务托盘显示系统通知,从而不用使用Nuget包。

toast 通知的结构

Toast 内容的核心组件有

  • launch:定义当用户单击你的 Toast 时将传回应用的参数,允许深层链接到 Toast 所显示的正确内容。
  • visual:toast 的可视部分,包括带有文本和图像的通用绑定。
  • actions:toast 的交互部分,包括输入和操作。
  • audio:控制向用户显示 Toast 时播放的音频。

Toast 内容的可视化表示形式:

Toast 内容介绍对toast各种应用场景进行了介绍,包括文本、文本行数、图片、徽章、时间戳、进度条、按钮、输入、音频等。

发送本地toast通知的操作步骤

新建项目NotificationLocalToast

安装NuGet包Microsoft.Toolkit.Uwp.Notifications

推荐 7.0 及以上版本。

如果.NET Framework的桌面应用仍使用 packages.config 管理包,需要将其迁移到PackageReference,否则不会正确引用Windows SDK。

迁移方法是:在项目中,右键单击“引用”,然后单击“将 packages.config 迁移到 PackageReference”。需要Visual Studio 2017 15.7 及更高版本才支持。

具体参见 从 packages.config 迁移到 PackageReference

注:迁移到PackageReference后,需要重启VS打开项目,否则无法正确的using引用到包库。

通知的发送(文本通知)

new ToastContentBuilder()
    .AddText("CodeMissing发来一条消息") // 标题文本
    .AddText("请检查消息内容,并及时处理")
    .Show(); // 7.0以上才提供Show方法

点击运行并发送消息,将在屏幕右下角看到toast通知

多次发送消息,会依照顺序各自依次显示(等待上一个进入操作中心或被关闭)。

处理点击通知的操作

当用户点击通知后,则会在后台线程调用ToastNotificationManagerCompat.OnActivated事件,在程序的该事件中处理交互操作。

如果应用程序关闭,将会启动exe应用(并且 ToastNotificationManagerCompat.WasCurrentProcessToastActivated()返回true,表示重新启动了进程),然后再在后台线程上调用 ToastNotificationManagerCompat.OnActivated 事件。

在主窗体的构造函数中处理该事件(如果不需要执行UI线程的操作,直接在Program.cs的Main函数入口处添加此监听事件即可)

public MainForm()
{
    InitializeComponent();

    // 监听通知激活(点击)
    ToastNotificationManagerCompat.OnActivated += toastArgs =>
    {
        // 通知参数
        ToastArguments args = ToastArguments.Parse(toastArgs.Argument);
        // 获取任何用户输入
        ValueSet userInput = toastArgs.UserInput;

        BeginInvoke(new Action( delegate
        {
            // TODO: UI线程的操作
            MessageBox.Show("Toast被激活(点击),参数是: " + toastArgs.Argument);
        }));
    };
}

当点击通知后,会显示对话框。

WPF中的(在入口程序中的)异步UI调用要通过Application.Current.Dispatcher.Invoke,它是位于System.Windows下的Application。需要添加引用PresentationFramework

// 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);
});

通知的卸载

如果应用有卸载程序,应该在卸载过程中调用ToastNotificationManagerCompat.Uninstall();

如果应用是不安装的“可移植应用”,则可根据需要在退出时调用(除非想要在退出后仍然保留通知)。

ToastNotificationManagerCompat.Uninstall()在执行后,会将通知面板中相关的信息清理掉。

卸载方法将清理任何计划通知和当前通知,删除任何关联的注册表值,并删除库创建的任何关联的临时文件。

设置通知的过期时间

忽略的toast通知会转到操作中心(通知中心),后续仍可以查看。

但是,通常消息都有一定的期限,过期后则不应该继续显示或保留,本地 toast 通知的默认和最长过期时间为 3 天。

下面设置过期时间为2天:

new ToastContentBuilder()
    .Show(toast =>
    {
        toast.ExpirationTime = DateTime.Now.AddDays(2);
    });

.NET应用使用Toast Notifications(.NET5+)

.NET中如果使用Microsoft.Toolkit.Uwp.Notifications,必须指定Windows TFM,且要指定window版本,至少为net6.0-windows10.0.17763.0或更高。否则,将报错找不到Show()方法。

  • 指定Windows TFM

右键项目,编辑项目文件,将TargetFramework指定为如下:

<TargetFramework>net6.0-windows10.0.17763.0</TargetFramework>

通常,指定TFM后,启动调试会报错没有xxx的目标,确保已运行还原...等错误。

解决办法是:清理项目,并重新生成一次即可。

有时候还会报错 net6.0-windows10.0.17763.0.Net框架版本不一致,需要修改为 net5.0-windows10.0.17763.0。或者改为net5后生成无错再改回net6;或者 直接清理项目并重新生成一次

添加图像

使用http图像

目前仅仅具有Internet功能的UWP/MSIX/sparse应用才支持http的图像【sparse,松散或稀疏应用】。

UWP/MSIX开发在Package.appxmanifest文件中用于指定Internet的能力(默认已经开启)

其他应用,比如Winform、WPF等必须将图像下载到本地,通过本地路径引用。

并且web图片引用有200KB的限制,具体参见官方文档介绍。不过有个不太清楚的地方:app's package是什么?又如何从其中获取图片?

Images can be used from the app's package, the app's local storage, or from the web. As of the Fall Creators Update, web images can be up to 3 MB on normal connections and 1 MB on metered connections. On devices not yet running the Fall Creators Update, web images must be no larger than 200 KB.

尝试通过资源pack的方式获取图片,未成功,比如WPF图片中可以使用的"pack://application:,,,/Resources/CSharp.png"

内联图像和主图

下载图片到本地,并添加到项目中,设置图片属性:复制到输出目录“总是”或“较新复制”、生成操作“无”,确保图片生成到exe程序路径。

首先获取img文件的完整路径,并创建Uri,通过AddInlineImageAddHeroImage添加为内联图像和主图。

  • 使用file:///构建uri
var imgFileFullPath = Path.GetFullPath("Resources/CSharp.png");
var fileUriString = $"file:///{imgFileFullPath}";
var imgUri = new Uri(fileUriString);

new ToastContentBuilder()
    .AddArgument("action", "viewConversation") // 添加相关参数
    .AddArgument("conversationId", 9813)
    .AddText("CodeMissing发来一张图片") // 标题文本
    .AddText("这是C#的图片")
    .AddInlineImage(imgUri) // 内联
    .AddHeroImage(imgUri) // 主图
    .Show();

注意本地文件的Uri访问协议:"file:///FileFullPath"
  • 直接使用文件路径创建Uri

new Uri(localImgPath)也可以创建uri。

var imgFileFullPath = Path.GetFullPath("Resources/CSharp.png");
           
new ToastContentBuilder()
    .AddText("这是C#的图片")
    .AddAppLogoOverride(new Uri(imgFileFullPath), ToastGenericAppLogoCrop.Circle)
    .Show();

徽标和剪裁(圆形图片)

new ToastContentBuilder()
    // ....
    .AddAppLogoOverride(imgUri, ToastGenericAppLogoCrop.Circle)
    .Show();

UWP使用http图片

new ToastContentBuilder()
    .AddArgument("action", "viewConversation") // 添加相关参数
    .AddArgument("conversationId", 9813)
    .AddText("CodeMissing发来一张图片") // 标题文本
    .AddText("这是C#的图片")
    .AddInlineImage(new Uri("https://www.vippng.com/png/detail/398-3984434_c-programming-png.png"))
    .AddAppLogoOverride(new Uri("https://www.vippng.com/png/detail/398-3984434_c-programming-png.png"), ToastGenericAppLogoCrop.Circle)
    .Show();

图片来源于网络

替换或删除指定通知

替换或移除toast通知需要使用Tag属性(以及Group属性),两者构成toast的主键。

为 toast 设置主键

new ToastContentBuilder()
    .AddText("我是含有Tag和Group的消息")
    .Show(toast =>
    {
        toast.Tag = "codemissing101";
        toast.Group = "codemissing";
    });

根据Tag和Group删除或替换toast

通过使用相同的Tag和Group再次发送消息,即可以实现替换。

new ToastContentBuilder()
    .AddText("我是替换的消息")
    .Show(toast =>
    {
        toast.Tag = "codemissing101";
        toast.Group = "codemissing";
    });

History.Remove 或者 RemoveGroup 实现移除

ToastNotificationManagerCompat.History.Remove("codemissing101", "codemissing");
如果只有Tag则只指定Tag,如果Tag和Group都存在,则两者都需要指定才能匹配。

清除通知

ToastNotificationManagerCompat.History.Clear();

参考

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

相关文章
|
4月前
|
开发框架 前端开发 JavaScript
C# 6.0+JavaScript云LIS系统源码  云LIS实验室信息管理新型解决方案
云LIS是为区域医疗提供临床实验室信息服务的计算机应用程序,可协助区域内所有临床实验室相互协调并完成日常检验工作,对区域内的检验数据进行集中管理和共享,通过对质量控制的管理,最终实现区域内检验结果互认。其目标是以医疗服务机构为主体,以医疗资源和检验信息共享为目标,集成共性技术及医疗服务关键技术,建立区域协同检验,最大化利用有限的医疗卫生资源。
149 1
|
4月前
|
前端开发 Java C#
java/C#语言开发的医疗信息系统11套源码
java/C#语言开发的医疗信息系统11套源码
87 2
|
1月前
|
关系型数据库 Java MySQL
C#winform中使用SQLite数据库
C#winform中使用SQLite数据库
45 3
C#winform中使用SQLite数据库
|
2月前
|
存储 Oracle 关系型数据库
PACS源码,C#语言数字医学影像系统成品源码
**数字医学影像系统(RIS/PACS)**采用C#开发,基于C/S架构,配Oracle数据库,具备自主版权,适用于项目实施。系统包含分诊、超声、放射、内镜、病理等工作站,支持基本信息维护、报表查询和系统维护。功能亮点有:WorkList管理、影像采集传输、存储检索、图像处理、多序列浏览、流程控制、报告录入与审核、支持多种影像设备及高级影像处理。RIS与PACS数据库同步,并集成HIS、电子病历等系统接口。全面遵循DICOM3.0标准。
PACS源码,C#语言数字医学影像系统成品源码
|
1月前
|
数据库
C#Winform使用NPOI获取word中的数据
C#Winform使用NPOI获取word中的数据
119 2
|
3月前
|
开发框架 前端开发 .NET
LIMS(实验室)信息管理系统源码、有哪些应用领域?采用C# ASP.NET dotnet 3.5 开发的一套实验室信息系统源码
集成于VS 2019,EXT.NET前端和ASP.NET后端,搭配MSSQL 2018数据库。系统覆盖样品管理、数据分析、报表和项目管理等实验室全流程。应用广泛,包括生产质检(如石化、制药)、环保监测、试验研究等领域。随着技术发展,现代LIMS还融合了临床、电子实验室笔记本和SaaS等功能,以满足复杂多样的实验室管理需求。
66 3
LIMS(实验室)信息管理系统源码、有哪些应用领域?采用C# ASP.NET dotnet 3.5 开发的一套实验室信息系统源码
|
2月前
|
数据采集 监控 BI
C#实验室检验LIS信息系统源码 微生物检验、质控维护
LIS系统的主要目标是为检验室开展检验工作提供更加有效的系统支持。该系统将尽量减少以人工操作的方式来实现信息转移,减少在接收检验项目、报告结果和保存记录等工作中可能会出现的人为误差,为检验结果查询提供更有效的方法,节省了管理信息所需的琐碎时间和精力。为实验室技术人员提供智能化的运行模式,使处理诸如按照规程审核检验结果、取消检验项目、分析、处理存在重大疑问的检验结果、执行特殊的命令和处理质量控制等问题更轻松自如,这将使检验人员更快地获得准确清晰的检验结果。为临床医护人员提供在线设施,使他们可以及时准确地获得相关实验室信息。确保检验结果的可靠性和准确性,利用实验室管理信息系统的仪器监控和质量控制,
30 0
|
2月前
|
C#
C#中使用IntPtr.Size属性来判断当前系统是32位还是64位
这段代码首先检查 `IntPtr.Size`的值,如果是4,则输出"当前系统是32位";如果是8,则输出"当前系统是64位";如果都不是,就输出"未知系统位数"。
33 0
|
4月前
|
存储 运维 BI
基于C#-VC-MSSQL开发的全套PACS系统源码 3D PACS系统源码:可实现医学影像获取、存档、观片、处理、打印多项应用
PACS的功能价值在于通过连接不同的影像设备,存储与管理图像,图像的调用与后处理,实现资源共享,降低成本,达到提高工作效率、提升医疗水平的目地;
55 1
基于C#-VC-MSSQL开发的全套PACS系统源码  3D PACS系统源码:可实现医学影像获取、存档、观片、处理、打印多项应用
|
4月前
|
安全 API C#
C#.Net筑基-类型系统②常见类型--枚举Enum
枚举(enum)是C#中的一种值类型,用于创建一组命名的整数常量。它们基于整数类型(如int、byte等),默认为int。枚举成员可指定值,未指定则从0开始自动递增。默认值为0。枚举可以与整数类型互相转换,并可通过`[Flags]`特性表示位域,支持位操作,用于多选场景。`System.Enum`类提供了如`HasFlag`、`GetName`等方法进行枚举操作。