WPF UI标准流水线

复制代码
流水线基类
cs 复制代码
    public class ViewModelBase : INotifyPropertyChanged
    {
        protected readonly TaskScheduler _uiScheduler;

        public ViewModelBase()
        {
            _uiScheduler = TaskScheduler.FromCurrentSynchronizationContext();
        }

        public event PropertyChangedEventHandler PropertyChanged;
        protected void OnPropertyChanged(string propertyName)
        {
            var handler = PropertyChanged;
            if (handler != null)
                handler(this, new PropertyChangedEventArgs(propertyName));
        }

        /// <summary>
        /// UI标准流水线:捕获状态→后台任务→更新UI→恢复状态
        /// </summary>
        protected void ExecuteWithUiPipeline<TState, TResult>(
            Func<TState> captureState,
            Func<TState, TResult> backgroundWork,
            Action<TResult> updateUi,
            Action<TState> restoreUi,
            Action<bool> busyFlagSetter)
        {
            busyFlagSetter(true);
            var state = captureState();

            Task.Factory.StartNew(() => backgroundWork(state))
            .ContinueWith(task =>
            {
                try
                {
                    if (task.Exception != null)
                    {
                        var ex = task.Exception.InnerException ?? task.Exception;
                        MessageBox.Show("操作异常:" + ex.Message);
                        return;
                    }
                    var result = task.Result;
                    updateUi(result);
                    restoreUi(state);
                }
                finally
                {
                    busyFlagSetter(false);
                }
            }, _uiScheduler);
        }
    }

子类使用示例

cs 复制代码
public class TreeViewModel : ViewModelBase
{
    private bool _isBusy;
    public bool IsBusy { get => _isBusy; set { _isBusy = value; OnPropertyChanged(nameof(IsBusy)); } }

    public void RefreshTree()
    {
        // 定义捕获状态
        Func<TreeState> capture = () => new TreeState
        {
            SelectedId = FindSelectedNode(TreeRoot)?.Id ?? -1,
            ExpandedIds = GetExpandedIds(TreeRoot)
        };

        // 后台工作
        Func<TreeState, List<NodeModel>> work = state => LoadDataFromDb();

        // 更新UI
        Action<List<NodeModel>> update = data =>
        {
            TreeRoot = new ObservableCollection<NodeViewModel>(BuildTree(data));
        };

        // 恢复状态
        Action<TreeState> restore = state =>
        {
            RestoreState(TreeRoot, state.SelectedId, state.ExpandedIds);
        };

        // 执行流水线
        ExecuteWithUiPipeline(capture, work, update, restore, busy => IsBusy = busy);
    }
}

🧠 总结

ViewModelBase 提供的这个流水线方法,本质上是将WPF异步编程中反复出现的"线程切换 + 状态管理"模式抽象为一个可复用的基础设施。它让子类代码更简洁、更聚焦于业务,同时保证了UI线程安全。你只需要在子类中实现具体的状态捕获、后台任务和UI恢复逻辑,框架自动帮你处理调度和异常。

如果你还想加入防重入 和版本号 功能,可以在子类中扩展,或者在ExecuteWithUiPipeline的基础上再封装一层,传入一个Func<bool>检查是否可以执行,或者集成CancellationToken。这个基类为更高级的封装提供了良好的起点。

相关推荐
wuyk5551 天前
PyQt6-第15讲-数据可视化QChart
python·ui·信息可视化·pyqt
光泽雨1 天前
WPF 音视频四大核心方案对比
wpf·音视频
浪扼飞舟2 天前
WPF(数据绑定)
wpf
samble3 天前
从零搭建半导体设备上位机(四):单实例、启动流程与配置文件,App 里那 526 行到底在干什么
wpf·配置文件·单实例
Autumn_ing3 天前
Pixso AI 如何按团队设计规范生成 UI?以消息设置页说明选库与验收
人工智能·ui·设计规范·pixso
不磕了还不行3 天前
用 Vue + Element UI 把元宝搜索的返回值做成“能点开检查的证据卡片”
前端·vue.js·ui
浪扼飞舟3 天前
WPF(控件的继承树、内容控件、布局控件)
wpf
OH_TPC5 天前
HarmonyOS APP开发---“动效君“UI动效素材库App,需要用到这个库
ui·华为·harmonyos·鸿蒙
小雨爱测6 天前
Photoshop 实战入门:从界面认知到第一张成品图
ui·photoshop
螺丝钉tina6 天前
[Playwright] [02]常用命令与调试:Debug UI、Mode和 Trace Viewer
开发语言·javascript·测试工具·ui·自动化