当前位置: 首页 > news >正文

详细介绍:C#的MVVM架构中的几种数据绑定方式

C#的MVVM架构中几种前端数据绑定方式

WPF基础框架

通过继承接口INotifyPropertyChangedICommand 来实现。

数据绑定部分

INotifyPropertyChanged原代码如下,WPF框架会自动注册DataContext对象中的PropertyChanged事件(若事件存在)。然后根据该事件修改前端属性。

namespace System.ComponentModel
{
// Notifies clients that a property value has changed.
public interface INotifyPropertyChanged
{
// Occurs when a property value changes.
event PropertyChangedEventHandler? PropertyChanged;
}
}

注意:INotifyPropertyChanged接口并非是强制要求的,当不需要通过设置属性自动修改页面数据时,也就是不需要执行set方法时,不需要继承该接口。若使用了通知集合ObservableCollection,也是不需要专门通过事件通知页面的。

public class NativeViewModel
: INotifyPropertyChanged
{
private string _name;
public string Name
{
get => _name;
set
{
if (_name != value)
{
_name = value;
OnPropertyChanged();
}
}
}
protected virtual void OnPropertyChanged([CallerMemberName] string? propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
<StackPanel><TextBox Text="{Binding Name}" />
</StackPanel>

数据绑定中的命令绑定

ICommand 原代码如下,可以看到其中有按钮操作常用的几种属性:是否可用、可用性变化、触发事件。与前端通过Click属性指定事件相比:一个是前端指定要执行的逻辑,一个是由vm来确定最终的执行逻辑,相当于是反转了控制方。可以根据需要使用、并非强制要求。

#nullable enable
using System.ComponentModel;
using System.Windows.Markup;
namespace System.Windows.Input
{
//
// 摘要:
// Defines a command.
[TypeConverter("System.Windows.Input.CommandConverter, PresentationFramework, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, Custom=null")]
[ValueSerializer("System.Windows.Input.CommandValueSerializer, PresentationFramework, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, Custom=null")]
public interface ICommand
{
//
// 摘要:
// Occurs when changes occur that affect whether or not the command should execute.
event EventHandler? CanExecuteChanged;
//
// 摘要:
// Defines the method that determines whether the command can execute in its current
// state.
//
// 参数:
// parameter:
// Data used by the command. If the command does not require data to be passed,
// this object can be set to null.
//
// 返回结果:
// true if this command can be executed; otherwise, false.
bool CanExecute(object? parameter);
//
// 摘要:
// Defines the method to be called when the command is invoked.
//
// 参数:
// parameter:
// Data used by the command. If the command does not require data to be passed,
// this object can be set to null.
void Execute(object? parameter);
}
}

对于ICommand属性,推荐使用方式是不要让其触发PropertyChanged,不应该被动态设置,而应该初始定好。不过如果使用场景确实需要,应该也是能生效的。

public class NativeViewModel
{
public ICommand GreetCommand {
get;
}
public NativeViewModel()
{
// 使用自定义的 RelayCommand 需要自己实现
GreetCommand = new RelayCommand();
}
}
// 需要实现的简单命令类
public class RelayCommand
: ICommand
{
// 略
}
<StackPanel><Button Content="Say Hello" Command="{Binding GreetCommand}" />
</StackPanel>

CommunityToolkit.Mvvm 方式

CommunityToolkit.Mvvm 利用 C# 的源码生成器,在编译时自动生成INotifyPropertyChangedICommand的样板代码。需要nuget包CommunityToolkit.Mvvm
其仅在vm上有区别,在实际绑定方式上没有区别。

using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
// 3. 使用 [ObservableObject] 特性或继承 ObservableObject
[ObservableObject]
public partial class ToolkitViewModel
{
// 4. 使用 [ObservableProperty] 标记字段,自动生成名为 "Name" 的属性
[ObservableProperty]
[NotifyCanExecuteChangedFor(nameof(GreetCommand))] // 当 Name 改变时,通知 GreetCommand 重新验证
private string _name;
[ObservableProperty]
private string _greeting;
// 5. 使用 [RelayCommand] 自动生成名为 GreetCommand 的 ICommand 属性
[RelayCommand(CanExecute = nameof(CanGreet))]
private void Greet()
{
Greeting = $"Hello from Toolkit, {
Name
}!";
}
private bool CanGreet() =>
!string.IsNullOrWhiteSpace(Name);
}

ReactiveUI

ReactiveUI 将响应式编程理念引入 MVVM,核心是使用ReactiveObjectWhenAnyValue等来声明数据流和反应关系。需要nuget包ReactiveUI.WPF
其仅在vm上有区别,在实际绑定方式上没有区别。

using ReactiveUI;
using System.Reactive.Linq;
// 6. 继承 ReactiveObject
public class ReactiveViewModel
: ReactiveObject
{
// 7. 使用 [Reactive] 特性或 WhenAnyValue
private string _name;
public string Name
{
get => _name;
set =>
this.RaiseAndSetIfChanged(ref _name, value);
}
private readonly ObservableAsPropertyHelper<
string> _greeting;
public string Greeting => _greeting.Value;
// 8. 使用 ReactiveCommand 创建命令
public ReactiveCommand<Unit, Unit> GreetCommand {get;}public ReactiveViewModel(){// 判断命令何时可执行:当 Name 不为空时var canGreet = this.WhenAnyValue(x => x.Name, name =>!string.IsNullOrWhiteSpace(name));// 创建命令GreetCommand = ReactiveCommand.CreateFromTask(execute: async () =>{/* 可以执行异步操作 */ return $"Hello from ReactiveUI, {Name}!";},canExecute: canGreet // 绑定可执行条件);// 9. 将命令的执行结果(一个IObservable<string>)订阅到 Greeting 属性_greeting = GreetCommand.ToProperty(this, x => x.Greeting, initialValue: "Waiting...");// 另一种更直接的写法(不通过命令结果):// GreetCommand = ReactiveCommand.Create(() => { Greeting = $"Hello from ReactiveUI, {Name}!"; }, canGreet);// 但上面那种方式展示了将 IObservable 流转换为属性的强大能力。}}
http://www.hskmm.com/?act=detail&tid=27780

相关文章:

  • 质量检验知识专题讲座之八:过程检验
  • 质量检验知识专题讲座之六:抽样检验步骤
  • 羡慕线段树
  • 质量检验知识专题讲座之七:来料检验
  • windows 10分区教程,win10自带分区教程
  • # Python 类中方法类型详解
  • 决斗(模拟赛题目T3)分析
  • 大学C语言课摸鱼记
  • gitlen中,已经提交了内容,如何回退到修改前?
  • CF1989F
  • 2025.10.10——1绿
  • Vue3水波纹指令:2025年Material Design交互新标准 - 实践
  • 巨型飞机运输风力涡轮机叶片技术解析
  • CCPC2024女生专场 游记(VP)
  • 重磅福利,JetBrains 宣布 DataGrip 面向非商业用途免费!
  • 【GitHub每日速递 251010】Zen MCP:一键 orchestrate 多 AI 模型,代码开发协作新革命!
  • 22 LCA模拟赛2T1 奶龙与贝利亚 题解
  • 微软拼音输入法自定义短语批量导入导出工具(支持Windows 10/11)
  • AI风险管控新规应对系统抵抗关闭行为
  • BLDC中的Q15
  • 华为 AP hw_manage 离线管理 Wi-Fi 密码
  • 雪落 - L
  • 251009
  • Mybatis笔记
  • PluginMonitor - Typecho 插件监控工具
  • LibreChat-图文并茂手把手教你搭建自己的AI机器人 Step-by-step guide to building your own chatbot
  • NOISG 2025 Prelim
  • STM32 教程
  • 先进反应堆:BWRX-300
  • ch58x/ch59x系列芯片Indication添加