H.Test.Message 示例项目学习教程

一、概述

H.Test.Message 是 WPF-Control 框架的消息系统示例项目,展示了如何使用框架提供的各种消息服务,包括:

  • 对话框消息(Dialog)
  • 通知消息(Notice)
  • 轻提示消息(Snack)
  • 表单消息(Form)

核心价值:通过统一的 IocMessage 服务,一行代码实现各种消息提示,无需手动创建窗口。


二、项目结构

H.Test.Message/
├── App.xaml          # 应用入口(XAML)
├── App.xaml.cs       # 应用入口(代码)
├── MainWindow.xaml   # 主窗口(XAML)
├── MainWindow.xaml.cs # 主窗口代码
└── H.Test.Message.csproj

三、核心文件解析

3.1 App.xaml.cs

public partial class App : ApplicationBase
{
    protected override void ConfigureServices(IServiceCollection services)
    {
        // 注册对话框消息服务
        services.AddSingleton<IDialogMessageService, AdornerDialogMessageService>();
        
        // 注册表单消息服务
        services.AddSingleton<IFormMessageService, FormMessageService>();
        
        // 注册通知消息服务
        services.AddNoticeMessage();
        
        // 注册轻提示消息服务
        services.AddSnackMessage();
        
        // 注册关于模块
        services.AddAbout();
    }

    protected override Window CreateMainWindow(StartupEventArgs e)
    {
        return new MainWindow();
    }
}

关键服务

服务 接口 实现 功能
对话框 IDialogMessageService AdornerDialogMessageService 模态对话框
表单 IFormMessageService FormMessageService 表单编辑对话框
通知 - NoticeMessage 右上角通知
轻提示 - SnackMessage 底部轻提示

3.2 MainWindow.xaml

<Window x:Class="H.Test.Message.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:h="https://github.com/HeBianGu"
        Title="MainWindow" Width="800" Height="450"
        Style="{StaticResource {x:Static WindowKeys.Default}}">
    
    <TabControl>
        <!-- Dialog 标签页 -->
        <TabItem Header="Dialog">
            <UniformGrid>
                <!-- 显示 IOC 注册的 Presenter -->
                <Button Command="{ShowIocCommand Type={x:Type IAboutViewPresenter}}"
                        Content="ShowIocCommand" />
                
                <!-- 显示消息对话框 -->
                <Button Command="{ShowMessageCommand Message=我是消息,Name=我是标题}"
                        Content="ShowMessageCommand" />
                
                <!-- 显示 Presenter -->
                <Button Command="{ShowCommand Presnter={h:GetStudent}}"
                        Content="ShowCommand" />
                
                <!-- 显示进度对话框 -->
                <Button Command="{ShowPercentCommand}"
                        Content="ShowPercentCommand" />
                
                <!-- 显示字符串对话框 -->
                <Button Command="{ShowStringCommand}"
                        Content="ShowStringCommand" />
                
                <!-- 显示等待对话框 -->
                <Button Command="{ShowWaitCommand}"
                        Content="ShowWaitCommand" />
                
                <!-- 显示编辑对话框 -->
                <Button Command="{ShowEditCommand Value={h:GetStudent}}"
                        Content="ShowEditCommand" />
                
                <!-- 显示标签页编辑对话框 -->
                <Button Command="{ShowTabEditCommand Value={h:GetStudent}}"
                        Content="ShowTabEditCommand" />
                
                <!-- 显示查看对话框 -->
                <Button Command="{ShowViewCommand Value={h:GetStudent}}"
                        Content="ShowViewCommand" />
                
                <!-- 内嵌弹窗 -->
                <Button Command="{h:ShowAdornerDialogCommand}"
                        CommandParameter="{h:GetStudent}"
                        Content="内嵌弹窗" />
            </UniformGrid>
        </TabItem>
        
        <!-- Notice 标签页 -->
        <TabItem Header="Notice">
            <UniformGrid>
                <Button Command="{h:ShowInfoNoticeMessageCommand Message=我是 Info 消息}"
                        Content="ShowInfo" />
                <Button Command="{h:ShowErrorNoticeMessageCommand Message=我是 Error 消息}"
                        Content="ShowError" />
                <Button Command="{h:ShowSuccessNoticeMessageCommand Message=我是 Success 消息}"
                        Content="ShowSuccess" />
                <Button Command="{h:ShowWarnNoticeMessageCommand Message=我是 Warn 消息}"
                        Content="ShowWarn" />
                <Button Command="{h:ShowFatalNoticeMessageCommand Message=我是 Fatal 消息}"
                        Content="ShowFatal" />
                <Button Command="{h:ShowProgressNoticeMessageCommand Message=我是 Progress 消息}"
                        Content="ShowProgress" />
            </UniformGrid>
        </TabItem>
        
        <!-- Snack 标签页 -->
        <TabItem Header="Snack">
            <UniformGrid>
                <Button Command="{h:ShowInfoSnackMessageCommand Message=我是 Info 消息}"
                        Content="ShowInfo" />
                <Button Command="{h:ShowErrorSnackMessageCommand Message=我是 Error 消息}"
                        Content="ShowError" />
                <Button Command="{h:ShowSuccessSnackMessageCommand Message=我是 Success 消息}"
                        Content="ShowSuccess" />
                <Button Command="{h:ShowWarnSnackMessageCommand Message=我是 Warn 消息}"
                        Content="ShowWarn" />
                <Button Command="{h:ShowFatalSnackMessageCommand Message=我是 Fatal 消息}"
                        Content="ShowFatal" />
                <Button Command="{h:ShowProgressSnackMessageCommand Message=我是 Progress 消息}"
                        Content="ShowProgress" />
            </UniformGrid>
        </TabItem>
        
        <!-- CommandMessage 标签页 -->
        <TabItem Header="CommandMessage">
            <UniformGrid>
                <!-- 异步消息命令 -->
                <Button Command="{h:AsyncMessageCommand Message=点击执行}"
                        Content="{Binding RelativeSource={RelativeSource Mode=Self}, 
                                          Path=Command.Message}" />
                
                <!-- 异步进度命令 -->
                <Button Command="{h:AsyncPercentCommand Value=0.0}"
                        Content="{Binding RelativeSource={RelativeSource Mode=Self}, 
                                          Path=Command.Value}" />
            </UniformGrid>
        </TabItem>
    </TabControl>
</Window>

四、消息系统详解

4.1 IocMessage 统一入口

public static class IocMessage
{
    // 对话框消息
    public static IDialogMessageService Dialog { get; }
    
    // 通知消息
    public static INoticeMessageService Notice { get; }
    
    // 轻提示消息
    public static ISnackMessageService Snack { get; }
    
    // 表单消息
    public static IFormMessageService Form { get; }
    
    // 窗口消息
    public static IWindowMessageService Window { get; }
}

4.2 对话框消息(Dialog)

基本使用
// 显示简单消息
IocMessage.Dialog.ShowMessage("操作成功", "提示");

// 显示等待对话框
using (var wait = IocMessage.Dialog.ShowWait("正在加载..."))
{
    // 执行耗时操作
    await Task.Delay(2000);
}

// 显示百分比进度
IocMessage.Dialog.ShowPercent("正在处理", 0.5);

// 显示字符串对话框
IocMessage.Dialog.ShowString("这是一段文本", "标题");
显示 Presenter
// 显示 IOC 注册的 Presenter
IocMessage.Dialog.ShowIoc<IAboutViewPresenter>();

// 显示自定义 Presenter
var student = new Student { Name = "张三", Age = 25 };
IocMessage.Dialog.ShowCommand(student);
编辑对话框
// 显示编辑对话框
var student = new Student { Name = "张三", Age = 25 };
bool? result = await IocMessage.Dialog.ShowEdit(student);

if (result == true)
{
    // 用户点击了确定
    Console.WriteLine($"编辑后的数据:{student.Name}");
}
带验证的表单
var student = new Student();
student.Age = 200;  // 不合法的年龄

// 带验证的编辑
Predicate<Student> match = x =>
{
    if (x.Age > 100)
    {
        IocMessage.Dialog.Show("年龄输入不合法");
        return false;
    }
    return true;
};

IocMessage.Form.ShowEdit(student, match);

4.3 通知消息(Notice)

基本类型
// Info 通知
IocMessage.Notice.ShowInfo("这是一条 Info 消息");

// Error 通知
IocMessage.Notice.ShowError("这是一条 Error 消息");

// Success 通知
IocMessage.Notice.ShowSuccess("这是一条 Success 消息");

// Warn 通知
IocMessage.Notice.ShowWarn("这是一条 Warn 消息");

// Fatal 通知
IocMessage.Notice.ShowFatal("这是一条 Fatal 消息");
进度通知
// 进度通知
IocMessage.Notice.ShowProgress("正在处理...", 0.5);
字符串通知
// 字符串通知
IocMessage.Notice.ShowString("自定义通知内容");
对话框通知
// 对话框通知
IocMessage.Notice.ShowDialog("需要用户确认的消息");

4.4 轻提示消息(Snack)

基本类型
// Info 轻提示
IocMessage.Snack.ShowInfo("这是一条 Info 消息");

// Error 轻提示
IocMessage.Snack.ShowError("这是一条 Error 消息");

// Success 轻提示
IocMessage.Snack.ShowSuccess("操作成功!");

// Warn 轻提示
IocMessage.Snack.ShowWarn("这是一条 Warn 消息");

// Fatal 轻提示
IocMessage.Snack.ShowFatal("这是一条 Fatal 消息");
进度轻提示
// 进度轻提示
IocMessage.Snack.ShowProgress("正在下载...", 0.75);
字符串轻提示
// 字符串轻提示
IocMessage.Snack.ShowString("自定义轻提示内容");

4.5 异步命令

异步消息命令
// 在 ViewModel 中使用
public ICommand AsyncMessageCommand { get; }

public MyViewModel()
{
    AsyncMessageCommand = new AsyncMessageCommand("点击执行");
}
异步进度命令
// 在 ViewModel 中使用
public ICommand AsyncPercentCommand { get; }

public MyViewModel()
{
    AsyncPercentCommand = new AsyncPercentCommand(0.0);
}

五、命令系统

5.1 对话框命令

命令 功能 参数
ShowMessageCommand 显示消息对话框 Message, Name, Width, Height
ShowPercentCommand 显示进度对话框 -
ShowStringCommand 显示字符串对话框 -
ShowWaitCommand 显示等待对话框 -
ShowEditCommand 显示编辑对话框 Value
ShowTabEditCommand 显示标签页编辑对话框 Value, TabNames
ShowViewCommand 显示查看对话框 Value
ShowIocCommand 显示 IOC 注册的 Presenter Type

5.2 通知命令

命令 功能 参数
ShowInfoNoticeMessageCommand Info 通知 Message
ShowErrorNoticeMessageCommand Error 通知 Message
ShowSuccessNoticeMessageCommand Success 通知 Message
ShowWarnNoticeMessageCommand Warn 通知 Message
ShowFatalNoticeMessageCommand Fatal 通知 Message
ShowProgressNoticeMessageCommand 进度通知 Message, Value

5.3 轻提示命令

命令 功能 参数
ShowInfoSnackMessageCommand Info 轻提示 Message
ShowErrorSnackMessageCommand Error 轻提示 Message
ShowSuccessSnackMessageCommand Success 轻提示 Message
ShowWarnSnackMessageCommand Warn 轻提示 Message
ShowFatalSnackMessageCommand Fatal 轻提示 Message
ShowProgressSnackMessageCommand 进度轻提示 Message, Value

六、运行项目

6.1 步骤

1. 打开 Visual Studio 2022
2. 打开解决方案:Solution/WPF-Control.sln
3. 在解决方案资源管理器中找到 H.Test.Message 项目
4. 右键点击项目 → 设置为启动项目
5. 按 F5 运行

6.2 预期效果

运行后会看到:

  • 一个包含 4 个标签页的窗口
  • Dialog:各种对话框按钮
  • Notice:通知消息按钮
  • Snack:轻提示消息按钮
  • CommandMessage:异步命令按钮

点击不同按钮会触发相应的消息提示。


七、实际应用案例

7.1 在 ViewModel 中使用

public class MainViewModel : Bindable
{
    private string _name;
    public string Name
    {
        get { return _name; }
        set { _name = value; RaisePropertyChanged(); }
    }

    // 保存命令
    public ICommand SaveCommand { get; }

    public MainViewModel()
    {
        SaveCommand = new RelayCommand(async x => await SaveAsync());
    }

    private async Task SaveAsync()
    {
        // 显示等待提示
        using (var wait = IocMessage.Dialog.ShowWait("正在保存..."))
        {
            try
            {
                // 模拟保存操作
                await Task.Delay(2000);
                
                // 保存成功
                IocMessage.Snack.ShowSuccess("保存成功!");
            }
            catch (Exception ex)
            {
                // 保存失败
                IocMessage.Notice.ShowError($"保存失败:{ex.Message}");
            }
        }
    }
}

7.2 带验证的表单编辑

public class UserEditViewModel : Bindable
{
    public ICommand EditUserCommand { get; }

    public UserEditViewModel()
    {
        EditUserCommand = new RelayCommand(x => EditUser());
    }

    private void EditUser()
    {
        var user = new User
        {
            Name = "张三",
            Email = "zhangsan@example.com",
            Age = 25
        };

        // 带验证的编辑
        Predicate<User> validator = u =>
        {
            if (string.IsNullOrEmpty(u.Name))
            {
                IocMessage.Dialog.ShowMessage("姓名不能为空", "验证失败");
                return false;
            }

            if (u.Age < 0 || u.Age > 150)
            {
                IocMessage.Dialog.ShowMessage("年龄必须在 0-150 之间", "验证失败");
                return false;
            }

            if (!u.Email.Contains("@"))
            {
                IocMessage.Dialog.ShowMessage("邮箱格式不正确", "验证失败");
                return false;
            }

            return true;
        };

        bool? result = IocMessage.Form.ShowEdit(user, validator);
        
        if (result == true)
        {
            IocMessage.Snack.ShowSuccess("用户信息更新成功!");
        }
    }
}

7.3 进度通知

public class DownloadViewModel : Bindable
{
    public ICommand DownloadCommand { get; }

    public DownloadViewModel()
    {
        DownloadCommand = new RelayCommand(async x => await DownloadAsync());
    }

    private async Task DownloadAsync()
    {
        // 显示进度对话框
        using (var progress = IocMessage.Dialog.ShowPercent("正在下载...", 0))
        {
            for (int i = 0; i <= 100; i++)
            {
                // 模拟下载
                await Task.Delay(100);
                
                // 更新进度
                progress.Update(i / 100.0);
                
                // 同时发送通知
                if (i % 10 == 0)
                {
                    IocMessage.Notice.ShowProgress($"下载进度:{i}%", i / 100.0);
                }
            }
        }

        IocMessage.Snack.ShowSuccess("下载完成!");
    }
}

八、消息类型对比

8.1 对话框 vs 通知 vs 轻提示

特性 对话框(Dialog) 通知(Notice) 轻提示(Snack)
显示位置 窗口中央 右上角 底部中央
模态 是(阻塞操作)
持续时间 用户关闭 自动消失(默认 3 秒) 自动消失(默认 2 秒)
适用场景 需要用户确认 重要通知 轻量提示
示例 确认删除、编辑表单 系统通知、错误提示 操作成功、加载中

8.2 选择建议

需要用户确认?
├─ 是 → 使用 Dialog(对话框)
│   ├─ 简单消息 → ShowMessage
│   ├─ 编辑数据 → ShowEdit
│   └─ 等待操作 → ShowWait
│
└─ 否 → 不需要用户确认
    ├─ 重要通知 → 使用 Notice(通知)
    │   ├─ 错误 → ShowError
    │   ├─ 成功 → ShowSuccess
    │   └─ 进度 → ShowProgress
    │
    └─ 轻量提示 → 使用 Snack(轻提示)
        ├─ 操作反馈 → ShowSuccess
        ├─ 加载提示 → ShowWait
        └─ 简单提示 → ShowInfo

九、常见问题

9.1 消息不显示

问题:调用消息服务后没有显示。

解决

1. 确保已注册对应的消息服务
2. 检查 IOC 容器是否正确构建
3. 确认在主线程中调用(UI 线程)

9.2 对话框无法关闭

问题:对话框显示后无法关闭。

解决

1. 使用 using 语句自动关闭
2. 手动调用 Close() 方法
3. 检查是否有未完成的异步操作

9.3 通知消息重叠

问题:多条通知消息重叠显示。

解决

1. 框架会自动排队显示
2. 可以调整通知显示时间
3. 手动关闭旧通知再显示新通知

十、总结

通过学习 H.Test.Message,您掌握了 WPF-Control 的消息系统:

  1. 对话框消息:模态对话框,用于确认、编辑、等待
  2. 通知消息:右上角通知,用于重要提示
  3. 轻提示消息:底部轻提示,用于轻量反馈
  4. 表单消息:自动表单编辑对话框
  5. 命令系统:内置命令简化使用

关键要点

  • 使用 IocMessage 统一访问所有消息服务
  • 对话框适合需要用户确认的场景
  • 通知适合重要提示
  • 轻提示适合轻量反馈
  • 内置命令可以在 XAML 中直接使用

最佳实践

  • 耗时操作使用 ShowWait 显示等待提示
  • 操作成功使用 Snack.ShowSuccess
  • 操作失败使用 Notice.ShowError
  • 需要确认使用 Dialog.ShowMessage

掌握这套消息系统,可以让您的应用交互更加专业和友好。

Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐