WPF笔记13——CommunityToolKit.Mvvm

1、[ObservableProperty]标记

private字段上有 [ObservableProperty]标记,CommunityToolkit.Mvvm会自动给它生成一个对应的public属性,并在属性值改变时自动触发属性变更通知。

2、[ObservableObject]标记

ObservableObject类型实现了实现了INotifyPropertyChanged和INotifyPropertyChanging接口,这使得对象的属性变化可以被观察到,从而实现数据绑定和通知机制。

3、[RelayCommand]标记

在 CommunityToolkit.Mvvm 包中,RelayCommand 是一个实现了 ICommand 接口的类,用于在 MVVM 模式中处理命令。RelayCommand 允许你将一个方法绑定到一个按钮或其他触发器上,当触发器被激活时,这个方法就会被调用。RelayCommand 还支持可执行性的检查,即在某些条件下命令可以被执行。

手写mvvm代码:

public partial class MyViewModel : INotifyPropertyChanged
{
private string _name;

public string Name
{
get{return _name;}
set{
_name=value;
this.RaiseNotifiedChanged(nameof(Name));
}
}

//DeletegateCommand是一个继承ICommand类的方法
public DeletegateCommand MyCommand { get; }

private void ExecuteCommand()
{
// 命令执行的逻辑
}

private bool CanExecuteCommand()
{
// 命令是否可以执行的逻辑
return true;
}

public event PropertyChangedEventHandler? PropertyChanged;

public void RaiseNotifiedChanged(string propertyName)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}

public MyViewModel ()
{
MyCommand = new DeletegateCommand(ExecuteCommand, ExecuteCommand);
}

}

使用CommunityToolkit.Mvvm.ComponentModel包后的代码

using CommunityToolkit.Mvvm.ComponentModel;

public partial class MyViewModel : ObservableObject
{
[ObservableProperty]
private string _name;

public ICommand MyCommand { get; }

public MyViewModel()
{
MyCommand = new RelayCommand(ExecuteCommand, CanExecuteCommand);
}

private void ExecuteCommand()
{
// 命令执行的逻辑
}

private bool CanExecuteCommand()
{
// 命令是否可以执行的逻辑
return true;
}

}

在上述代码中,CommunityToolkit.Mvvm会在编译时生成以下等效代码:

using CommunityToolkit.Mvvm.ComponentModel;

public partial class MyViewModel : ObservableObject
{
private string _name;

public string Name
{
get => _name;
set => SetProperty(ref _name, value);
}

[RelayCommand] //[RelayCommand] 特性直接在方法上,这样可以自动生成一个以方法名加 Command 后缀的 RelayCommand
private void ExecuteCommand()
{
// 命令执行的逻辑
}
}

补充:

1、使用 [ObservableProperty] 和 [NotifyCanExecuteChangedFor] 特性

对于需要根据某个属性的值来决定命令是否可执行的情况,可以使用 [NotifyCanExecuteChangedFor] 特性。

这个特性允许我们指定一个命令,当指定的属性值变化时,会自动通知命令的 CanExecute 方法重新评估。

例如下面代码,当IsEnable属性发生变化时,ButtonClickCommand 的可执行性会自动更新

[ObservableProperty]
[NotifyCanExecuteChangedFor(nameof(ButtonClickCommand))]
private bool isEnable;

[RelayCommand(CanExecute = nameof(CanButtonClick))]
private void ButtonClick()
{
// 命令执行的逻辑
}

private bool CanButtonClick() => IsEnable;

2、异步版本的RelayCommand

如果我们需要执行异步操作,可以使用异步版本的RelayCommand。

这样,我们可以在命令执行的方法中使用await,而不用担心阻塞UI线程。

例如下代码,允许我们在命令中执行异步操作,同时保持UI的响应性

[RelayCommand(CanExecute = nameof(CanButtonClick))]
private async Task ButtonClick()
{
await Task.Delay(1500);
// 命令执行的逻辑
}

3、命令添加参数

3.1、使用 [RelayCommand] 和 [RelayCommandParameter] 特性:

我们可以使用 [RelayCommand] 特性来自动创建命令,并使用 [RelayCommandParameter] 特性来指定命令的参数。

using CommunityToolkit.Mvvm.Input;

public class MyViewModel : ObservableObject
{
[RelayCommand]
[RelayCommandParameter]
private void ExecuteCommand(string parameter)
{
// 使用参数执行命令
Console.WriteLine($"Command executed with parameter: {parameter}");
}
}

//在xaml中绑定命令
//s:RelayCommand 标记扩展来绑定命令,这是 CommunityToolkit.Mvvm 源代码生成器提供的功能。


</DataGridTemplateColumn.CellTemplate>

step3、使用 RelativeSource 找到 ViewModel:

RelativeSource 用于找到当前按钮的祖先 DataGrid,然后通过 Path=DataContext 找到 ViewModel。这是因为 Button 本身的 DataContext 是当前行的 Student 对象,而我们需要命令的 DataContext 是 ViewModel。

step4、在 ViewModel 中处理命令:

当按钮被点击时,OnStudentSelected 方法会被调用,并且当前行的 Student 对象作为参数传递

这个过程还可以简化写成下面这样:

step1、定义 ViewModel:

在我们的 ViewModel 中,使用 [RelayCommand] 特性来定义一个命令。

using CommunityToolkit.Mvvm.Input;

public class MyViewModel : ObservableObject
{
[RelayCommand]
private void OnStudentSelected(Student student)
{
// 这里处理学生对象
}
}

step2、在 XAML 中绑定命令:

在 DataGrid 的按钮列中,使用 s:RelayCommand 来绑定命令,并使用 DataGrid 的 DataContext 来传递当前行的 Student 对象。

s:RelayCommand 是一个标记扩展,它会自动为你创建一个 RelayCommand 实例,并绑定到 ViewModel 中的方法。ViewModel=DataContext 指定了命令的 ViewModel,而 s:RelayCommandParameter="{Binding}" 传递了当前行的 DataContext(即 Student 对象)作为命令的参数。




<DataGridTemplateColumn.CellTemplate>

posted @ 2024-12-30 12:25  长松入霄汉远望不盈尺  阅读(2773)  评论(0)    收藏  举报