WPF 异步命令实现

参考

  • 豆包

环境

软件/系统 版本 说明
Windows windows 10 专业版 22H2 64 位操作系统, 基于 x64 的处理器
Microsoft Visual Studio Community 2022 (64 位) - Current 版本 17.13.6
.NET Framework 4.8

部分代码

  1. AsyncRelayCommand.xaml
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    using System.Windows.Input;
    
    namespace WpfApp1
    {
    	public class AsyncRelayCommand : ICommand
    	{
    		private readonly Func<Task> _execute;
    		private readonly Func<bool> _canExecute;
    		private bool _isExecuting;
    
    		public AsyncRelayCommand(Func<Task> execute, Func<bool> canExecute = null)
    		{
    			_execute = execute;
    			_canExecute = canExecute;
    		}
    
    		public event EventHandler CanExecuteChanged
    		{
    			add => CommandManager.RequerySuggested += value;
    			remove => CommandManager.RequerySuggested -= value;
    		}
    
    		public bool CanExecute(object parameter)
    		{
    			return !_isExecuting && (_canExecute?.Invoke() ?? true);
    		}
    
    		public async void Execute(object parameter)
    		{
    			if (CanExecute(parameter))
    			{
    				try
    				{
    					_isExecuting = true;
    					await _execute();
    				}
    				finally
    				{
    					_isExecuting = false;
    				}
    
    				// 触发CanExecuteChanged事件,更新命令状态
    				CommandManager.InvalidateRequerySuggested();
    			}
    		}
    	}    }
    
  2. ViewModelBase.cs
    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Linq;
    using System.Runtime.CompilerServices;
    using System.Text;
    using System.Threading.Tasks;
    
    namespace WpfApp1
    {
    	public class ViewModelBase : INotifyPropertyChanged
    	{
    		public event PropertyChangedEventHandler PropertyChanged;
    
    		public void OnPropertyChanged([CallerMemberName] string propName = null)
    		{
    			PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propName));
    		}
    
    	}
    }
    
    
  3. MainWindowVM.cs
    using System;
    using System.Collections.Generic;
    using System.Diagnostics;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    using System.Windows;
    using System.Windows.Input;
    
    namespace WpfApp1
    {
    	public class MainWindowVM : ViewModelBase
    	{
    
    		// 需要显式设置 get读取器才能在 XAML 中绑定
    		public ICommand MyAsyncCommand { get; }
    
    		public MainWindowVM()
    		{
    			MyAsyncCommand = new AsyncRelayCommand(ExecuteMyAsyncCommand);
    		}
    
    		private async Task ExecuteMyAsyncCommand()
    		{
    			// 执行异步操作
    			await Task.Run(() =>
    			{
    
    				// 模拟耗时操作
    				System.Threading.Thread.Sleep(2000);
    				// 在 UI 线程中更新
    				Application.Current.Dispatcher.Invoke(() =>
    				{
    					MessageBox.Show("12312");
    				});
    				Debug.WriteLine(12312);
    			});
    		}
    	}
    }
    
    

同步命令

  1. RelayCommand.cs
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    using System.Windows.Input;
    
    namespace WpfApp1
    {
    	public class RelayCommand : ICommand
    	{
    		private readonly Func<Task> _execute;
    		private readonly Func<bool> _canExecute;
    
    		public RelayCommand(Func<Task> execute, Func<bool> canExecute = null)
    		{
    			_execute = execute ?? throw new ArgumentNullException(nameof(execute));
    			_canExecute = canExecute;
    		}
    
    		public event EventHandler CanExecuteChanged
    		{
    			add => CommandManager.RequerySuggested += value;
    			remove => CommandManager.RequerySuggested -= value;
    		}
    
    		public bool CanExecute(object parameter) => _canExecute?.Invoke() ?? true;
    
    		public async void Execute(object parameter) => await _execute();
    	}
    }
    
    
posted @ 2025-06-05 16:29  夏秋初  阅读(112)  评论(0)    收藏  举报