RelayCommand是CommunityToolkit.Mvvm库中非常强大的命令实现,它简化了MVVM模式中命令的创建和使用。本文将详细探讨RelayCommand的各种应用场景。

C#using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
namespace App06
{
// ViewModel
public partial class UserViewModel : ObservableObject
{
// 无参数同步命令
[RelayCommand]
private void SaveUser()
{
// 执行保存用户逻辑
MessageBox.Show("用户信息已保存");
}
// 带条件的同步命令
[RelayCommand(CanExecute = nameof(CanSaveUser))]
private void SaveUserWithCondition()
{
MessageBox.Show("带条件的用户保存");
}
// 命令是否可执行的条件方法
private bool CanSaveUser() => !string.IsNullOrEmpty(UserName);
// 属性
private string _userName;
public string UserName
{
get => _userName;
set
{
// 使用SetProperty更新属性并通知UI
SetProperty(ref _userName, value);
// 触发命令的可执行状态更新
SaveUserWithConditionCommand.NotifyCanExecuteChanged();
}
}
}
}
C#namespace App06
{
public partial class Form1 : Form
{
private UserViewModel _viewModel;
public Form1()
{
InitializeComponent();
// 初始化ViewModel
_viewModel = new UserViewModel();
// 绑定数据和命令
BindViewModel();
}
private void BindViewModel()
{
// 文本框绑定UserName属性
txtUserName.DataBindings.Add(
new Binding("Text", _viewModel, "UserName", true,
DataSourceUpdateMode.OnPropertyChanged)
);
// 绑定无条件保存按钮
btnSaveUser.Click += (s, e) => _viewModel.SaveUserCommand.Execute(null);
// 绑定带条件保存按钮
btnSaveUserWithCondition.Click += (s, e) =>
_viewModel.SaveUserWithConditionCommand.Execute(null);
// 初始时禁用带条件的保存按钮
btnSaveUserWithCondition.Enabled = false;
// 监听命令的可执行状态变化
_viewModel.SaveUserWithConditionCommand.CanExecuteChanged +=
(s, e) =>
{
btnSaveUserWithCondition.Enabled =
_viewModel.SaveUserWithConditionCommand.CanExecute(null);
};
}
}
}

C#using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
namespace App06
{
public partial class NetworkViewModel : ObservableObject
{
private readonly HttpClient _httpClient;
private CancellationTokenSource _cts;
// 数据属性
private string _fetchedData;
public string FetchedData
{
get => _fetchedData;
set => SetProperty(ref _fetchedData, value);
}
// 加载状态属性
private bool _isLoading;
public bool IsLoading
{
get => _isLoading;
set => SetProperty(ref _isLoading, value);
}
// 错误信息属性
private string _errorMessage;
public string ErrorMessage
{
get => _errorMessage;
set => SetProperty(ref _errorMessage, value);
}
public NetworkViewModel()
{
// 初始化HttpClient
_httpClient = new HttpClient();
}
// 异步命令示例
[RelayCommand]
public async Task FetchDataAsync()
{
// 取消之前的请求
_cts?.Cancel();
_cts = new CancellationTokenSource();
try
{
IsLoading = true;
var token = _cts.Token;
var response = await _httpClient.GetAsync("https://jsonplaceholder.typicode.com/posts/1");
response.EnsureSuccessStatusCode();
FetchedData = await response.Content.ReadAsStringAsync();
}
catch (OperationCanceledException)
{
ErrorMessage = "请求已取消";
}
catch (HttpRequestException ex)
{
ErrorMessage = $"网络请求失败: {ex.Message}";
}
finally
{
IsLoading = false;
}
}
}
}
C#using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using static System.Windows.Forms.VisualStyles.VisualStyleElement;
namespace App06
{
public partial class Form2 : Form
{
private bool InverseBoolean(bool value) => !value;
private NetworkViewModel _viewModel;
public Form2()
{
InitializeComponent();
// 初始化ViewModel
_viewModel = new NetworkViewModel();
// 绑定ViewModel
BindViewModel();
}
private void BindViewModel()
{
// 绑定数据显示
txtFetchedData.DataBindings.Add(
new Binding("Text", _viewModel, "FetchedData", true,
DataSourceUpdateMode.OnPropertyChanged)
);
// 绑定错误消息
lblErrorMessage.DataBindings.Add(
new Binding("Text", _viewModel, "ErrorMessage", true,
DataSourceUpdateMode.OnPropertyChanged)
);
// 进度条绑定
pbar.DataBindings.Add(
new Binding("Visible", _viewModel, "IsLoading", true,
DataSourceUpdateMode.OnPropertyChanged)
);
}
private async void btnFetchData_Click(object sender, EventArgs e)
{
try
{
btnFetchData.Enabled = false;
await _viewModel.FetchDataAsync();
}
catch (Exception ex)
{
MessageBox.Show($"执行失败: {ex.Message}", "错误",
MessageBoxButtons.OK, MessageBoxIcon.Error);
}
finally
{
// 始终确保按钮可用
btnFetchData.Enabled = true;
}
}
}
}

C#using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace App06
{
// 用户模型
public class User
{
public string Name { get; set; }
public int Age { get; set; }
}
}
C#using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
namespace App06
{
// ViewModel
public partial class ParameterCommandViewModel : ObservableObject
{
// 属性绑定
[ObservableProperty]
private string nameInput;
[ObservableProperty]
private int ageInput;
// 接收字符串参数的命令
[RelayCommand]
private void ProcessName(string name)
{
MessageBox.Show($"处理名称: {name}");
}
// 接收复杂对象参数的命令
[RelayCommand]
private void UpdateUser(User user)
{
MessageBox.Show($"更新用户: {user.Name}, 年龄: {user.Age}");
}
// 创建用户的命令
[RelayCommand]
private void CreateUser()
{
var newUser = new User
{
Name = NameInput,
Age = AgeInput
};
UpdateUser(newUser);
}
}
}
C#using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Xml.Linq;
namespace App06
{
public partial class Form3 : Form
{
private ParameterCommandViewModel viewModel;
public Form3()
{
InitializeComponent();
InitializeViewModel();
SetupBindings();
}
private void InitializeViewModel()
{
viewModel = new ParameterCommandViewModel();
}
private void SetupBindings()
{
// 绑定文本框到ViewModel的属性
txtName.DataBindings.Add(
"Text",
viewModel,
nameof(ParameterCommandViewModel.NameInput),
true,
DataSourceUpdateMode.OnPropertyChanged
);
txtAge.DataBindings.Add(
"Text",
viewModel,
nameof(ParameterCommandViewModel.AgeInput),
true,
DataSourceUpdateMode.OnPropertyChanged
);
// 绑定按钮到命令
btnProcessName.Click += (s, e) =>
viewModel.ProcessNameCommand.Execute(txtName.Text);
btnCreateUser.Click += (s, e) =>
viewModel.CreateUserCommand.Execute(null);
}
}
}

RelayCommand默认在UI线程执行CommunityToolkit.Mvvm的RelayCommand提供了强大且灵活的命令实现方式,极大地简化了MVVM开发中的命令逻辑。
本文作者:技术老小子
本文链接:
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!