MVVM与命令模式的搭配使用场景
在开发WPF或Vue这类支持数据绑定的前端项目时,经常会遇到按钮点击后需要执行一段逻辑,同时还要控制按钮是否可用。如果直接在视图层写事件处理函数,很快代码就会变得混乱。这时候,把MVVM模式和命令模式结合起来,能大大提升代码的可维护性。
比如做一个记账小程序,有一个“保存”按钮。用户填写完金额和分类后点击保存,数据存入数据库;但如果金额为空,按钮就得禁用。这种交互逻辑如果全堆在XAML或Vue模板里,后期改需求时容易出错。
用ICommand封装操作
在WPF中,可以定义一个实现了ICommand接口的类来代表“保存”这个动作。它不仅包含执行逻辑,还能根据当前状态决定按钮是否可用。ViewModel只需要暴露一个SaveCommand属性,View通过绑定自动响应变化。
public class SaveCommand : ICommand
{
private Action _execute;
private Func<bool> _canExecute;
public SaveCommand(Action execute, Func<bool> canExecute)
{
_execute = execute;
_canExecute = canExecute;
}
public event EventHandler CanExecuteChanged;
public bool CanExecute(object parameter)
{
return _canExecute();
}
public void Execute(object parameter)
{
_execute();
}
public void RaiseCanExecuteChanged()
{
CanExecuteChanged?.Invoke(this, EventArgs.Empty);
}
}在ViewModel中集成命令
ViewModel里持有一个SaveCommand实例,并将它的可执行条件与表单有效性绑定。当用户输入金额时,触发属性变更通知,命令自动刷新状态。
public class ExpenseViewModel : INotifyPropertyChanged
{
private decimal _amount;
public decimal Amount
{
get => _amount;
set
{
_amount = value;
OnPropertyChanged();
((SaveCommand)SaveCommand).RaiseCanExecuteChanged();
}
}
public ICommand SaveCommand { get; private set; }
public ExpenseViewModel()
{
SaveCommand = new SaveCommand(
execute: () => MessageBox.Show("已保存!"),
canExecute: () => Amount > 0
);
}
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged([CallerMemberName] string name = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
}
}视图层只需简单绑定
XAML中不需要写Click事件,所有交互都通过绑定完成。这样视图只关心展示,逻辑全部集中在ViewModel中,测试和复用都更方便。
<StackPanel>
<TextBox Text="{Binding Amount}" />
<Button Content="保存" Command="{Binding SaveCommand}" />
</StackPanel>类似的思路也可以用在Vue组件中,把“命令”抽象成一个对象,包含handler和enabled字段,父组件通过props传递给自定义按钮组件,实现一致的行为控制方式。