MAUI 中使用 DI 及 MVVM
创始人
2024-02-20 23:17:27
0

MAUI 中使用 DI 及 MVVM

  • 为什么要使用 依赖注入 和 MVVM
  • 如何在 MAUI 中使用依赖注入
  • 如何使用 MVVM
    • 不使用框架或组件
      • 定义一个 BaseViewModel
      • MainViewModel 的实现
      • MainPage 中进行 Binding
    • 使用组件优化前面的 ViewModel 代码
  • 基项目的效果

为什么要使用 依赖注入 和 MVVM

MVVM 和 依赖注入 有助于开发出松耦合可维护以及可测试的应用程序。

如何在 MAUI 中使用依赖注入

依赖注入在MAUI中是原生支持的。
创建一个MAUI APP项目,根目录会有 MauiProgram.cs

public static MauiApp CreateMauiApp()
{var builder = MauiApp.CreateBuilder();builder.UseMauiApp().ConfigureFonts(fonts =>{fonts.AddFont("OpenSans-Regular.ttf", "OpenSansRegular");});// 注入页面builder.Services.AddTransient();return builder.Build();
}
  • 在 builder 中注入需要的页面或服务即可

如何使用 MVVM

不使用框架或组件

  • 先说下不使用任何框架或组件是如何实现的。

定义一个 BaseViewModel

BaseViewModel 会被后来的 viewmodel 所继承,并且所有的公共属性、方法都将再次进行声明。
BaseViewModel 需要继承和实现 INotifyPropertyChanged 才能够实现 viewviewmodel 之间的通讯。

using System.ComponentModel;
using System.Runtime.CompilerServices;namespace CrossPlatformTools.ViewModel
{public class BaseViewModel : INotifyPropertyChanged{private bool isBusy;public bool IsBusy{get => isBusy;set{if (isBusy == value)return;isBusy = value;OnPropertyChanged();OnPropertyChanged(nameof(IsNoteBusy));}}public bool IsNoteBusy => !IsBusy;private string title;public string Title{get => title;set{if (title == value)return;title = value;OnPropertyChanged();}}public event PropertyChangedEventHandler PropertyChanged;public void OnPropertyChanged([CallerMemberName] string name = null) =>PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));}
}

MainViewModel 的实现

MainViewModel 继承 BaseViewModel 但是 MainViewModel 中独有的属性和方法还是需要的MainViewModel 中进行声明的。

namespace CrossPlatformTools.ViewModel
{public class MainViewModel : BaseViewModel{private int count = 0;public int Count{get { return count; }set{if (count == value)return;count = value;OnPropertyChanged();}}public Command CountCommand { get; }public MainViewModel(){Title = "首页";CountCommand = new Command(OnCounter);}private void OnCounter(){Count++;}}
}

在 BaseViewModel 声明的属性 MainViewModel 中就可以直接使用了。
Command 的声明相比于通知属性就简便很多。声明 Command 然后在构造函数中调用即可。

MainPage 中进行 Binding

在 xaml 中需要引入命名空间:
xmlns:viewmodel="clr-namespace:CrossPlatformTools.ViewModel"

只引入命名空间这时想要使用属性是无法提示的,还需要设置 DataType
x:DataType="viewmodel:MainViewModel"



你以为这样就完了吗,当然不是,只在xaml中引入命名空间进行 CommandProperty 的Binding 是不行了,还要进行上下文绑定。

using CrossPlatformTools.ViewModel;namespace CrossPlatformTools.View;public partial class MainPage : ContentPage
{public MainPage(MainViewModel mainViewModel){InitializeComponent();BindingContext = mainViewModel;}
}

这里有的一不同点,一般来说 BindingContext 是这样做的 BindingContext = new MainViewModel() 但是我这里使用的是构造函数注入。
不能直接使用 需要在 MauiProgram.cs 中注入才能使用。

使用组件优化前面的 ViewModel 代码

原生的方式实现 MVVM 时, ViewModel 中的属性定义非常需要很多的代码,并且要手动实现 PropertyChanged 事件。

  • 使用 CommunityToolkit.Mvvm 实现

官方描述:
此包包含一个.NET MVVM库,其中包含以下帮助程序:

  • ObservableObject:实现INotifyPropertyChanged接口的对象的基类。
  • ObservableRecipient:支持IMessenger服务的可观察对象的基类。
  • ObservableValidator:实现INotifyDataErrorInfo接口的对象的基类。
  • RelayCommand:一个实现ICommand接口的简单委托命令。
  • AsyncRelayCommand:支持异步操作和取消的委托命令。
  • WeakReferenceMessenger:通过不同的松散耦合对象交换消息的消息传递系统。
  • StrongReferenceMessenger:一个高性能的消息传递系统,以弱引用换取速度。
  • Ioc:用于配置依赖注入服务容器的助手类。
  • CommunityToolkit.Mvvm 是基于 .NET Standard 实现,理论上适用于所有 .NET 平台应用。

需要引入 CommunityToolkit.Mvvm.ComponentModel 命名空间
使用 partial class 标识符,CommunityToolkit.Mvvm 内部实现使用的是源生成器,所有需要使用 partial 进行标识。
变量的声明必须使用驼峰式命名规则,才可以与生成的以 Pascal 命名规则的属性名不重复。

  • 关于 源生成器 不明白的可以去看前面的文章 C# 源代码生成器 讲解了 源生成器的用法。

  • 基类就变成了下面这样,少了很多的代码

using CommunityToolkit.Mvvm.ComponentModel;namespace CrossPlatformTools.ViewModel
{public partial class BaseViewModel : ObservableObject{[ObservableProperty][NotifyPropertyChangedFor(nameof(isNoteBusy))]bool isBusy;bool isNoteBusy => !isBusy;[ObservableProperty]string title;}
}
  • 同样的 MainViewModel 代码也是要进行更改的,精简了很多。
using CommunityToolkit.Mvvm.ComponentModel;namespace CrossPlatformTools.ViewModel
{public partial class MainViewModel : BaseViewModel{[ObservableProperty]private int count = 0;public Command CountCommand { get; }public MainViewModel(){Title = "首页";CountCommand = new Command(OnCounter);}private void OnCounter(){Count++;}}
}

基项目的效果

效果

相关内容

热门资讯

“乌克兰国际索赔委员会”成立,... 【环球时报驻俄罗斯特派记者 肖新新】据乌通社等媒体16日报道,35个国家和欧盟16日在荷兰海牙签署公...
做实公益诉讼 守护峡江文脉(法... 本报记者 姜 峰 图①:重庆市忠县人民检察院检察官现场查看石宝寨寨门。 张海波摄 图②:重庆市巫溪...
法院:驳回诉讼请求 员工举报上司职场霸凌反被起诉侵犯名誉权 法院:驳回诉讼请求 员工向公司领导、同事发送邮件举报上司职...
大唐电信科技股份有限公司关于公... 本公司董事会及全体董事保证本公告内容不存在任何虚假记载、误导性陈述或者重大遗漏,并对其内容的真实性、...
深圳广田集团股份有限公司 关于... 本公司及董事会全体成员保证信息披露的内容真实、准确、完整,没有虚假记载、误导性陈述或重大遗漏。 深圳...
广东华特气体股份有限公司 关于... 本公司董事会及全体董事保证本公告内容不存在任何虚假记载、误导性陈述或者重大遗漏,并对其内容的真实性、...
英国推出新措施打击侵害妇女和女... 中新社伦敦12月17日电 (欧阳开宇 刘施岑)英国内政部17日宣布推出一项打击侵害妇女和女童暴力犯罪...
海南封关绘就开放新图景 上市公... 图①为三亚大东海旅游区。 图②为海口复兴城互联网信息产业园。 图③为博鳌乐城国际医疗旅游先行区。...
法国内政部网络系统遭入侵:数据... 大象新闻2025-12-17 23:06:30 法国内政部长洛朗·努内兹17日接受法国新闻广播电台采...