Files
XplorePlane/XP.Common/Documents/GeneralForm.README.md
T

8.4 KiB
Raw Blame History

通用窗体使用指南 | General Form Usage Guide

概述 | Overview

XP.Common.GeneralForm 提供 XplorePlane 项目中可复用的通用 WPF 窗体组件。当前包含以下窗体:

窗体 说明
ProgressWindow 模态进度条窗口,支持线程安全的进度更新和关闭操作
InputDialog 通用输入对话框,支持单行文本输入、可选验证和多语言按钮

目录结构 | Directory Structure

XP.Common/GeneralForm/
├── ViewModels/
│   ├── InputDialogViewModel.cs       # 输入对话框 ViewModel
│   └── ProgressWindowViewModel.cs    # 进度窗口 ViewModel
└── Views/
    ├── InputDialog.xaml              # 输入对话框 XAML 视图
    ├── InputDialog.xaml.cs           # 输入对话框 Code-Behind
    ├── ProgressWindow.xaml           # 进度窗口 XAML 视图
    └── ProgressWindow.xaml.cs        # 进度窗口 Code-Behind

ProgressWindow 进度条窗口

功能特性 | Features

  • 模态进度条窗口,居中显示,不可调整大小
  • 线程安全:UpdateProgress()Close() 可从任意线程调用,内部自动通过 Dispatcher 调度
  • 可配置是否允许用户手动关闭窗口(isCancelable 参数)
  • 不可取消时,通过 Win32 API 禁用窗口关闭按钮(灰色不可点击)
  • 进度值自动 Clamp 到 [0, 100] 范围,超出范围时记录 Warn 日志
  • 自动继承主窗口图标
  • 使用 Telerik RadProgressBar 控件(Crystal 主题)

构造函数参数 | Constructor Parameters

public ProgressWindow(
    string title = "操作进行中",       // 窗口标题
    string message = "请稍候...",      // 提示信息
    bool isCancelable = true,          // 是否允许用户关闭窗口
    ILoggerService? logger = null      // 日志服务(可选)
)
参数 类型 默认值 说明
title string "操作进行中" 窗口标题栏文本
message string "请稍候..." 进度条上方的提示信息
isCancelable bool true true:用户可手动关闭;false:禁用关闭按钮
logger ILoggerService? null 传入日志服务后自动记录窗口生命周期日志

公开方法 | Public Methods

UpdateProgress - 更新进度

// 线程安全,可从任意线程调用
void UpdateProgress(string message, double progress)
  • message:更新提示信息文本
  • progress:进度值(0-100),超出范围自动修正

Close - 关闭窗口

// 线程安全,可从任意线程调用(隐藏基类 Window.Close()
new void Close()

基本用法 | Basic Usage

using XP.Common.GeneralForm.Views;
using XP.Common.Logging.Interfaces;

public class SomeService
{
    private readonly ILoggerService _logger;

    public SomeService(ILoggerService logger)
    {
        _logger = logger?.ForModule<SomeService>() 
            ?? throw new ArgumentNullException(nameof(logger));
    }

    public async Task ExecuteLongOperation()
    {
        // 创建进度窗口(不可取消)
        var progressWindow = new ProgressWindow(
            title: "数据处理中",
            message: "正在初始化...",
            isCancelable: false,
            logger: _logger);

        // 显示模态窗口(需在 UI 线程调用)
        // 注意:ShowDialog() 会阻塞,通常配合 Task 使用
        _ = Task.Run(async () =>
        {
            try
            {
                progressWindow.UpdateProgress("正在加载数据...", 20);
                await Task.Delay(1000); // 模拟耗时操作

                progressWindow.UpdateProgress("正在处理数据...", 60);
                await Task.Delay(1000);

                progressWindow.UpdateProgress("即将完成...", 90);
                await Task.Delay(500);

                progressWindow.UpdateProgress("完成", 100);
            }
            finally
            {
                // 关闭窗口(线程安全)
                progressWindow.Close();
            }
        });

        progressWindow.ShowDialog();
    }
}

允许用户取消的用法 | Cancelable Usage

// 创建可取消的进度窗口
var progressWindow = new ProgressWindow(
    title: "文件导出",
    message: "正在导出文件...",
    isCancelable: true,   // 用户可以点击关闭按钮取消
    logger: _logger);

progressWindow.ShowDialog();

ViewModel 绑定属性 | ViewModel Binding Properties

ProgressWindowViewModel 继承自 BindableBase,提供以下可绑定属性:

属性 类型 说明
Title string 窗口标题(只读)
Message string 提示信息文本(可通知)
Progress double 进度值 0-100(可通知)
ProgressText string 百分比显示文本,如 "75%"(只读,自动计算)
IsCancelable bool 是否允许用户关闭(只读)

注意事项 | Notes

  1. ShowDialog() 必须在 UI 线程调用,它会阻塞当前线程直到窗口关闭
  2. UpdateProgress()Close() 内部已处理跨线程调度,可安全地从后台线程调用
  3. isCancelable = false 时,窗口关闭按钮会被 Win32 API 禁用(灰色),用户无法通过 Alt+F4 或点击关闭
  4. 进度值超出 [0, 100] 范围时会自动修正并记录 Warn 级别日志
  5. Close() 使用 new 关键字隐藏基类方法(因 Window.Close() 非虚方法),确保通过 ProgressWindow 类型引用调用

InputDialog 输入对话框

功能特性 | Features

  • 模态输入对话框,居中于父窗口显示,不可调整大小
  • 自动继承主窗口图标
  • 按钮文本支持多语言(使用 Button_OK / Button_Cancel 资源键)
  • 可选的输入验证委托(Func<string, string?>),验证失败时在输入框下方显示红色错误提示
  • 输入内容变化时自动清除验证错误
  • 使用 Telerik RadWatermarkTextBoxRadButton 控件(Crystal 主题)
  • 提供静态 Show() 便捷方法,一行代码即可调用

静态方法 | Static Method

public static string? Show(
    string prompt,                        // 提示文本
    string title,                         // 窗口标题
    string defaultValue = "",             // 默认值
    Func<string, string?>? validate = null, // 验证委托(可选)
    Window? owner = null                  // 父窗口(可选)
)
参数 类型 默认值 说明
prompt string 必填 输入框上方的提示文本
title string 必填 窗口标题栏文本
defaultValue string "" 输入框的初始值
validate Func<string, string?>? null 验证委托:返回 null 表示通过,返回错误信息则阻止确认
owner Window? null 父窗口,设置后对话框居中于父窗口

返回值:用户输入的字符串,取消时返回 null

基本用法 | Basic Usage

using XP.Common.GeneralForm.Views;

// 最简用法,无验证
var name = InputDialog.Show("请输入名称:", "新建项目");
if (name == null) return; // 用户取消

// 带默认值
var port = InputDialog.Show("请输入端口号:", "配置", "8080");

带验证的用法 | Usage with Validation

// 验证委托:返回 null 表示通过,返回错误信息则显示在输入框下方
var groupId = InputDialog.Show(
    "请输入 Group ID",
    "新增 Group",
    validate: input =>
    {
        if (string.IsNullOrWhiteSpace(input))
            return "ID 不能为空";
        if (existingIds.Contains(input))
            return "ID 已存在,请使用不同的 ID";
        return null; // 验证通过
    });

// 验证非负整数
var dbNumber = InputDialog.Show(
    "请输入 DB 块号(非负整数):",
    "新增 Group",
    "0",
    validate: input =>
    {
        if (!int.TryParse(input, out int val) || val < 0)
            return "必须为非负整数";
        return null;
    });

注意事项 | Notes

  1. Show() 必须在 UI 线程调用(内部使用 ShowDialog()
  2. 验证委托在用户点击确定按钮时执行,验证失败不会关闭对话框
  3. 用户修改输入内容时会自动清除上一次的验证错误提示
  4. 按钮文本从 XP.Common 资源文件读取(Button_OK / Button_Cancel),自动跟随应用语言