闽公网安备 35020302035485号

2.绑定命令,在WPF中,为了解决事件响应功能之间的耦合,提出了绑定命令思想,即命令可以绑定的方式与控件建立联系。绑定命令必须实现ICommand接口。


using System.ComponentModel;
using System.Runtime.CompilerServices;
namespace DemoMVVM.Core
{
/// <summary>
/// 堆代码 duidaima.com
/// 可被观测的类
/// </summary>
public abstract class ObservableObject : INotifyPropertyChanged
{
/// <summary>
/// 属性改变事件
/// </summary>
public event PropertyChangedEventHandler? PropertyChanged;
/// <summary>
/// 属性改变触发方法
/// </summary>
/// <param name="propertyName">属性名称</param>
protected void RaisePropertyChanged([CallerMemberName]string propertyName=null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
/// <summary>
/// 设置属性值,如果发生改变,则调用通知方法
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="target"></param>
/// <param name="value"></param>
/// <param name="propertyName"></param>
/// <returns></returns>
protected bool SetProperty<T>(ref T target,T value, [CallerMemberName] string propertyName = null)
{
if (EqualityComparer<T>.Default.Equals(target, value))
{
return false;
}
else
{
target=value;
RaisePropertyChanged(propertyName);
return true;
}
}
}
}
注意:上述SetProperty主要用于将普通属性,变为具备通知功能的属性。namespace DemoMVVM.Core
{
/// <summary>
/// ViewModel基类,继承自ObservableObject
/// </summary>
public abstract class ViewModelBase:ObservableObject
{
}
}
2. 具备绑定功能的命令namespace DemoMVVM.Core
{
public class DelegateCommand : ICommand
{
private Action<object> execute;
private Predicate<object> canExecute;
public event EventHandler? CanExecuteChanged;
public DelegateCommand(Action<object> execute, Predicate<object> canExecute)
{
if (execute == null)
{
throw new ArgumentNullException("execute 不能为空");
}
this.execute = execute;
this.canExecute = canExecute;
}
public DelegateCommand(Action<object> execute):this(execute,null)
{
}
public bool CanExecute(object? parameter)
{
return canExecute?.Invoke(parameter)!=false;
}
public void Execute(object? parameter)
{
execute?.Invoke(parameter);
}
}
}
注意,DelegateCommand的构造函数,接收两个参数,一个是Execute(干活的),一个是CanExecute(判断是否可以干活的)。using DemoMVVM.Core;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime;
using System.Text;
using System.Threading.Tasks;
namespace DemoMVVM
{
public class MainWindowViewModel:ViewModelBase
{
#region 属性及构造函数
private double leftNumber;
public double LeftNumber
{
get { return leftNumber; }
set { SetProperty(ref leftNumber , value); }
}
private double rightNumber;
public double RightNumber
{
get { return rightNumber; }
set { SetProperty(ref rightNumber , value); }
}
private double resultNumber;
public double ResultNumber
{
get { return resultNumber; }
set { SetProperty(ref resultNumber , value); }
}
public MainWindowViewModel()
{
}
#endregion
#region 命令
private DelegateCommand operationCommand;
public DelegateCommand OperationCommand
{
get {
if (operationCommand == null)
{
operationCommand = new DelegateCommand(Operate);
}
return operationCommand; }
}
private void Operate(object obj)
{
if(obj == null)
{
return;
}
var type=obj.ToString();
switch (type)
{
case "+":
this.ResultNumber = this.LeftNumber + this.RightNumber;
break;
case "-":
this.ResultNumber = this.LeftNumber - this.RightNumber;
break;
case "*":
this.ResultNumber = this.LeftNumber * this.RightNumber;
break;
case "/":
if (this.RightNumber == 0)
{
this.ResultNumber = 0;
}
else
{
this.ResultNumber = this.LeftNumber / this.RightNumber;
}
break;
}
}
#endregion
}
}
创建视图,并在视图中进行数据绑定,将ViewModel和UI关联起来,如下所示:<Window x:Class="DemoMVVM.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:DemoMVVM"
mc:Ignorable="d"
Title="MVVM示例" Height="350" Width="600">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition></ColumnDefinition>
<ColumnDefinition></ColumnDefinition>
<ColumnDefinition Width="0.3*"></ColumnDefinition>
<ColumnDefinition></ColumnDefinition>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition></RowDefinition>
<RowDefinition></RowDefinition>
<RowDefinition></RowDefinition>
<RowDefinition></RowDefinition>
</Grid.RowDefinitions>
<StackPanel Grid.Row="1" Grid.Column="0" Orientation="Horizontal">
<TextBlock Text="A1:" VerticalAlignment="Center" ></TextBlock>
<TextBox Margin="10" Width="120" Height="35" Text="{Binding LeftNumber, UpdateSourceTrigger=PropertyChanged}" VerticalContentAlignment="Center"></TextBox>
</StackPanel>
<StackPanel Grid.Row="1" Grid.Column="1" Orientation="Horizontal">
<TextBlock Text="A2:" VerticalAlignment="Center" ></TextBlock>
<TextBox Margin="10" Width="120" Height="35" Text="{Binding RightNumber, UpdateSourceTrigger=PropertyChanged}" VerticalContentAlignment="Center"></TextBox>
</StackPanel>
<TextBlock Grid.Row="1" Grid.Column="2" Text="=" VerticalAlignment="Center" HorizontalAlignment="Center"></TextBlock>
<StackPanel Grid.Row="1" Grid.Column="3" Orientation="Horizontal">
<TextBlock Text="A3:" VerticalAlignment="Center" ></TextBlock>
<TextBox Margin="10" Width="120" Height="35" Text="{Binding ResultNumber, UpdateSourceTrigger=PropertyChanged}" VerticalContentAlignment="Center"></TextBox>
</StackPanel>
<StackPanel Grid.Row="2" Grid.ColumnSpan="4" Orientation="Horizontal" HorizontalAlignment="Center">
<Button Content="+" Width="100" Height="35" Margin="10" Command="{Binding OperationCommand}" CommandParameter="+"></Button>
<Button Content="-" Width="100" Height="35" Margin="10" Command="{Binding OperationCommand}" CommandParameter="-"></Button>
<Button Content="*" Width="100" Height="35" Margin="10" Command="{Binding OperationCommand}" CommandParameter="*"></Button>
<Button Content="/" Width="100" Height="35" Margin="10" Command="{Binding OperationCommand}" CommandParameter="/"></Button>
</StackPanel>
</Grid>
</Window>
注意,在xaml前端UI代码中,分别对TextBox的Text和Button的Command进行了绑定,已达到数据驱动UI,以及UI响应客户的功能。namespace DemoMVVM
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
private MainWindowViewModel viewModel;
public MainWindow()
{
InitializeComponent();
viewModel = new MainWindowViewModel();
this.DataContext = viewModel;
}
}
}
MVVM实例演示
通过以上步骤,已经完成了MVVM的简单应用。实例演示如下:
