ToastNotifications Tutorial

Posted by Andy Feng on July 19, 2025

Introduction .NET9 无法使用

ToastNotifications 是一个专为 .NET WPF 应用设计的轻量级库,用于在桌面端显示 临时通知消息(类似Windows系统Toast通知)。其核心特点是:

  • 非侵入式:通知从屏幕边缘弹出,不打断用户操作。
  • 可定制:支持位置、动画、样式和交互。
  • 低耦合:无需复杂依赖,直接集成到现有项目。 ToastNotifications 核心对象是 Notifier 类,你需要创建一个 Notifier 实例,指定通知位置、生命周期等,然后使用它发送通知。

应用场景

|场景|示例|推荐配置| |—|—|—| |操作反馈|文件保存成功/失败提示|ShowSuccess()/ShowError()| |后台任务完成|下载完成、数据处理结束|ShowAsync() + 自动关闭| |用户确认|删除确认、二次验证|带交互按钮的通知| |实时监控|服务器状态报警|持久化通知(需手动关闭)|

Install

install

 Install via nuget:

Install-Package ToastNotifications
Install-Package ToastNotifications.Messages

Import ToastNotifications.Messages theme in App.xaml

<Application.Resources>
    <ResourceDictionary>
        <ResourceDictionary.MergedDictionaries>
            <ResourceDictionary Source="pack://application:,,,/ToastNotifications.Messages;component/Themes/Default.xaml" />
        </ResourceDictionary.MergedDictionaries>
    </ResourceDictionary>
</Application.Resources>

基本用法

创建通知接口 INotificationService

public interface INotificationService
{
    void ShowSuccess(string message);
    void ShowError(string message);
    void ShowWarning(string message);
    void ShowInformation(string message);
}

加入DI

实现

    public class ToastNotificationService : INotificationService
    {
        private readonly ToastNotifier _notifier;

        public ToastNotificationService(ToastNotifier notifier)
        {
            _notifier = notifier;
        }

        public void ShowSuccess(string message) => _notifier.ShowSuccess(message);
        public void ShowError(string message) => _notifier.ShowError(message);

        public void ShowWarning(string message) =>_notifier.ShowWarning(message);
        public void ShowInformation(string message)
        {
            throw new NotImplementedException();
        }
    }

App.xaml.cs

private void ConfigureServices(IServiceCollection services)
    {
        // 注册ToastNotifier为单例(推荐)INoticationService
        services.AddSingleton<INoticationService>(provider => 
        {
            var notifier = new ToastNotifier(cfg =>
            {
                cfg.Position = NotificationPosition.BottomRight;
                cfg.MaxItems = 3;
            });
            return notifier;
        });

        // 注册主窗口和其他服务
        services.AddTransient<MainWindow>();
        services.AddTransient<MainViewModel>();
    }

其他配置细节

创建对象,初始化配置

// 初始化配置
var notifier = new ToastNotifier(cfg =>
{
    cfg.Position = NotificationPosition.BottomRight; // 位置(Top/Bottom/Left/Right)
    cfg.MaxItems = 3;                                // 最大同时显示数
    cfg.AnimationType = AnimationType.Fade;          // 动画类型(Fade/Slide)
    cfg.DisplayTime = TimeSpan.FromSeconds(5);       // 显示时长
});

或直接Create Notifier instance

using ToastNotifications;
using ToastNotifications.Lifetime;
using ToastNotifications.Position;
/* * */
Notifier notifier = new Notifier(cfg =>
{
    cfg.PositionProvider = new WindowPositionProvider(
        parentWindow: Application.Current.MainWindow,
        corner: Corner.TopRight,
        offsetX: 10,  
        offsetY: 10);

    cfg.LifetimeSupervisor = new TimeAndCountBasedLifetimeSupervisor(
        notificationLifetime: TimeSpan.FromSeconds(3),
        maximumNotificationCount: MaximumNotificationCount.FromCount(5));

    cfg.Dispatcher = Application.Current.Dispatcher;
});

交互支持

// 带按钮的通知
notifier.Show("确认删除?", 
    confirmationButtons: new[] { "确定", "取消" },
    onClick: buttonText => 
    {
        if (buttonText == "确定") DeleteFile();
    });

集成

view 集成

<!-- MainWindow.xaml -->
<Window ...
        xmlns:toast="clr-namespace:ToastNotifications;assembly=ToastNotifications">
        <!-- 通知容器 -->
        <toast:ToastNotifier x:Name="Notifier" Position="BottomRight"/>
</Window>

mvvm集成

// 在ViewModel中通过服务调用
public class MainViewModel
{
    private readonly INoticationService _notifier;
    
    public MainViewModel(INoticationService notifier)
    {
        _notifier = notifier;
        SaveCommand = new RelayCommand(() => _notifier.ShowSuccess("保存成功"));
    }
}

建议用法

实现通知服务 NotificationService

using ToastNotifications;
using ToastNotifications.Messages;
using ToastNotifications.Lifetime;
using ToastNotifications.Position;

public class NotificationService : INotificationService, IDisposable
{
    private readonly Notifier _notifier;

    public NotificationService()
    {
        _notifier = new Notifier(cfg =>
        {
            cfg.PositionProvider = new WindowPositionProvider(
                parentWindow: Application.Current.MainWindow, // 确保主窗口已加载
                corner: Corner.TopRight,
                offsetX: 10,
                offsetY: 10);

            cfg.LifetimeSupervisor = new TimeAndCountBasedLifetimeSupervisor(
                notificationLifetime: TimeSpan.FromSeconds(3),
                maximumNotificationCount: MaximumNotificationCount.FromCount(5));

            cfg.Dispatcher = Application.Current.Dispatcher;
        });
    }

    public void ShowSuccess(string message) => _notifier.ShowSuccess(message);
    public void ShowError(string message) => _notifier.ShowError(message);
    public void ShowWarning(string message) => _notifier.ShowWarning(message);
    public void ShowInformation(string message) => _notifier.ShowInformation(message);

    public void Dispose() => _notifier.Dispose();
}

在 DI 容器中注册服务

public partial class App : Application
{
    public static IServiceProvider Services { get; private set; }

    protected override void OnStartup(StartupEventArgs e)
    {
        var services = new ServiceCollection();

        // 注册你的其他服务
        services.AddSingleton<INotificationService, NotificationService>();

        Services = services.BuildServiceProvider();

        base.OnStartup(e);
    }
}

集成

View 中创建 ViewModel 并注入notification service

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
        var notificationService = App.Services.GetRequiredService<INotificationService>();
        DataContext = new MainViewModel(notificationService);
    }
}

view model

public class MainViewModel
{
    private readonly INotificationService _notificationService;

    public MainViewModel(INotificationService notificationService)
    {
        _notificationService = notificationService;
    }

    public void Submit()
    {
        _notificationService.ShowSuccess("保存成功!");
    }
}

Use provided messages

通知类型

|方法|效果|示例代码| |—|—|—| |ShowSuccess|绿色成功通知(带✓图标)|notifier.ShowSuccess("保存成功")| |ShowError|红色错误通知(带×图标)|notifier.ShowError("文件读取失败")| |ShowInformation|蓝色信息通知(带i图标)|notifier.ShowInfo("新版本可用")| |ShowWarning|黄色警告通知(带!图标)|notifier.ShowWarning("磁盘空间不足")|

using ToastNotifications.Messages;
/* * */
notifier.ShowInformation(message);
notifier.ShowSuccess(message);
notifier.ShowWarning(message);
notifier.ShowError(message);

清理资源(可选)

Dispose notifier when it’s no longer needed 当窗口关闭时,记得调用 _notifier.Dispose() 避免资源泄露:

public void Dispose()
{
    _notifier.Dispose();
}

可放在 MainWindow.OnClosedApp.OnExit 里调用。 如果你用的是 Application.Current.MainWindow,确保在主窗体关闭时清理 Notifier

protected override void OnExit(ExitEventArgs e)
{
    (App.Services.GetService<INotificationService>() as IDisposable)?.Dispose();
    base.OnExit(e);
}

高级配置

自定义UI模板

<!-- 定义自定义通知样式 -->
<DataTemplate x:Key="CustomToastTemplate">
    <Border Background="#FF444444" CornerRadius="5">
        <TextBlock Text="{Binding Message}" Foreground="White" Margin="10"/>
    </Border>
</DataTemplate>

使用模版

// 应用模板
notifier.UseCustomTemplate((Notification notification) => 
    Application.Current.FindResource("CustomToastTemplate"));

队列控制

// 清空所有通知
notifier.ClearAll();

// 暂停/恢复显示
notifier.Pause();
notifier.Resume();

异步通知

await notifier.ShowAsync("后台处理完成");

FAQ

问题 解决方案
通知被其他窗口遮挡 设置Topmost="True"或使用Windowless模式
高DPI显示模糊 在App.xaml中添加<Application.Resources><Style TargetType="Notification" BasedOn="{StaticResource {x:Type Notification}}"/></Application.Resources>
MVVM下无法直接绑定 通过IToastNotifier接口注入服务

References

ToastNotifications Github