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

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

CSDN私自将文章改成了VIP文章,所以在这里也发一遍。

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 enableusing 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] 特性或 WhenAnyValueprivate 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.jsqmd.com/news/358191/

相关文章:

  • 少儿编程体验课推荐:如何根据学习目标选购最适合的课程 - 品牌测评鉴赏家
  • 探究分布式电源接入对电网的影响:基于MATLAB的分析
  • AI元人文:多元共生与价值原语 ——智能时代文明操作系统的哲学构想
  • 建议收藏|倾心之选的AI论文工具 —— 千笔·专业学术智能体
  • python新能源汽车数据分析大屏可视化系统(设计源文件+万字报告+讲解)(支持资料、图片参考_相关定制)_文章底部可以扫码
  • 2026年重庆白癜风医院推荐厂家推荐:重庆皮肤病医院哪家好、重庆皮肤病医院在哪里、重庆皮肤病医院官网选择指南 - 优质品牌商家
  • 计算机毕设java学校机房管理系统 基于SpringBoot的高校计算机实验室智能管理平台 JavaWeb驱动的校园机房资源调度与服务系统
  • 2026年口碑好的搅拌装备制造商汇总,搅拌装备定制超专业 - myqiye
  • 如何在一天内改变你的整个人生(英中对照)• I
  • Java集合框架详解
  • Day31事件委托
  • 文档上传漏洞
  • 干式细胞复苏仪服务商家怎么选择,科默斯值得考虑吗 - mypinpai
  • 司拉德帕Seladelpar改善原发性胆汁性胆管炎患者瘙痒症状的剂量
  • 金维达电热等电热管制造商哪家口碑好 - 工业设备
  • 基于python商品数据分析可视化预测系统(设计源文件+万字报告+讲解)(支持资料、图片参考_相关定制)_文章底部可以扫码
  • 2026年福州纵横美术口碑排名,看看教学理念和质量怎么样 - 工业推荐榜
  • 步步高超市卡回收,闲置秒变现金的省心之选 - 京顺回收
  • 【YOLOv11安全帽识别系统】(设计源文件+万字报告+讲解)(支持资料、图片参考_相关定制)_文章底部可以扫码全!
  • 2026年奕思瑞品牌质量好吗,儿童益智玩具热门推荐盘点 - 工业品牌热点
  • tiktok 2026 X-Gnarly
  • 2025-2026全屋装配式企业怎么选?这份选购指南帮你找到靠谱品牌 - 匠言榜单
  • [前后端分离]springboot+vue的基于hive安顺旅游景点数据分析系统(368)(设计源文件+万字报告+讲解)(支持资料、图片参考_相关定制)_文章底部可以扫码
  • 2026年高性价比rohs检测仪优质生产商排名,快来了解 - 工业设备
  • Obsidian
  • 西安熟石灰费用多少,盘点靠谱的熟石灰供应商 - mypinpai
  • 2026年咸阳靠谱白灰生产厂推荐,熟悉生产流程企业汇总 - 工业推荐榜
  • 如何选择适合孩子学习人工智能的教育机构? - 品牌测评鉴赏家
  • 探讨施乐复印机租赁收费价目表,深圳复印机租赁公司怎么选择? - myqiye
  • 测度论Measure theory