MAUI笔记
.NET MAUI 基础知识总结含路由跳转 弹窗详解PDA系统登录、增删改查、路由跳转、下拉选择案例链接https://download.csdn.net/download/ly1h1/92846901?spm1001.2014.3001.5503一、什么是 .NET MAUI.NET MAUI.NET Multi-platform App UI是微软推出的跨平台移动 / 桌面 UI 框架核心优势是「一套代码多端运行」无需为不同平台Android、iOS、Windows、macOS单独开发极大降低跨平台开发成本。核心特点开发语言C# XAML界面描述语言上手门槛低适合.NET 开发者快速转型移动端性能接近原生应用避免跨平台框架常见的性能损耗集成能力内置 MVVM、路由导航、网络请求、布局控件等全套开发能力无需额外引入第三方库适用场景移动应用手机端、平板应用也可扩展到桌面应用二、MAUI 项目核心结构实战对应版结合我们开发的智慧农业项目标准 MAUI 项目结构如下新手重点记这 5 个核心目录 / 文件plaintextagricultureMobile项目名 ├── Views // 页面目录所有界面都在这里 │ ├── LoginView.xaml // 登录页项目入口 │ ├── FarmView.xaml // 新增数据页 │ ├── ShedView.xaml // 数据列表页改/删功能 │ └── EditView.xaml // 编辑数据页 ├── ViewModels // 业务逻辑目录MVVM核心 │ ├── LoginViewModel.cs // 登录逻辑 │ ├── FarmViewModel.cs // 新增逻辑下拉选择 │ ├── ShedViewModel.cs // 列表修改删除逻辑 │ └── EditViewModel.cs // 编辑逻辑 ├── Models // 数据模型目录 │ └── DataItem.cs // 数据实体A1Real、A2String、A3String ├── AppShell.xaml // 路由导航配置页面跳转核心 └── MauiProgram.cs // 应用服务注册程序启动入口关键说明Views只写界面XAML不写任何业务逻辑保证「界面与逻辑分离」ViewModels所有业务逻辑网络请求、数据处理、按钮点击事件都在这里AppShell.xaml管理所有页面的路由控制页面跳转规则是 MAUI 导航的核心三、XAML 基础MAUI 界面开发语言XAML 是 MAUI 的界面描述语言类似 HTML语法简洁专注于「描述界面布局和控件」无需写代码就能完成界面开发。1. 常用布局控件实战高频布局控件用于控制页面元素的排列方式我们项目中全部用到新手重点掌握前 3 个表格控件名称作用项目实战应用场景Grid /网格布局最常用、最稳定实现列表滚动、按钮并排VerticalStackLayout /垂直排列从上到下页面整体垂直布局、列表项内部布局HorizontalStackLayout /水平排列从左到右按钮并排修改 删除ScrollView /滚动视图新增页、登录页避免内容溢出CollectionView /列表控件展示多条数据大棚数据列表展示实战示例Grid 布局解决列表不滚动问题xml!-- 根布局用Grid实现列表正常滚动 -- Grid RowDefinitionsAuto,* !-- 第1行刷新按钮自适应高度 -- Button Grid.Row0 Text刷新数据 Command{Binding LoadCommand} / !-- 第2行列表占满剩余所有空间支持滚动 -- CollectionView Grid.Row1 ItemsSource{Binding Items} / /Grid2. 常用输入 / 展示控件实战高频表格控件名称作用项目实战应用场景Label /文本展示显示 “数值XXX”“参数 2XXX”Entry /文本输入框输入用户名、密码、A1Real、A2StringPicker /下拉选择框A3String 下拉选择 A/B/CButton /按钮触发事件登录、提交、修改、删除、刷新Border /圆角边框美化界面图片、表单美化Image /图片展示项目 Logo、大棚图片实战示例Picker 下拉选择框xml!-- 下拉选择框绑定ViewModel中的数据源 -- Picker BackgroundColor#F5F5F5 Title请选择参数3 ItemsSource{Binding A3Options} SelectedItem{Binding A3String}/四、MVVM 模式MAUI 标准开发方式MVVM 是 MAUI 开发的核心模式核心思想是「界面View与业务逻辑ViewModel分离」便于维护和扩展我们的项目全程采用这种模式。1. MVVM 三要素对应项目实战表格要素作用项目对应文件View界面XAML只负责展示LoginView.xaml、ShedView.xaml 等ViewModel业务逻辑处理数据、网络请求、事件LoginViewModel.cs、ShedViewModel.cs 等Model数据模型存储数据结构DataItem.csA1Real、A2String 等2. 核心接口INotifyPropertyChanged必写作用实现 “数据变化 → 界面自动更新”比如输入框输入内容、下拉选择后界面同步显示最新数据是 MVVM 绑定的核心。固定模板所有 ViewModel 都要继承并实现直接复制使用csharp运行using System.ComponentModel; using System.Runtime.CompilerServices; namespace agricultureMobile.ViewModels { public class BaseViewModel : INotifyPropertyChanged { // 事件数据变化时触发 public event PropertyChangedEventHandler? PropertyChanged; // 触发事件的方法固定写法 protected void OnPropertyChanged([CallerMemberName] string? propertyName null) { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); } } }实战示例ViewModel 中使用csharp运行// 继承BaseViewModel无需重复写INotifyPropertyChanged public class FarmViewModel : BaseViewModel { // 私有字段 private string _a2String string.Empty; // 公共属性绑定到界面 public string A2String { get _a2String; set { _a2String value; OnPropertyChanged(); // 数据变化时通知界面更新 } } }五、数据绑定 BindingMAUI 灵魂数据绑定是连接 View 和 ViewModel 的桥梁实现「界面与数据的自动关联」无需手动操作界面控件减少代码冗余。1. 核心语法实战常用xml!-- 界面控件绑定 ViewModel 中的属性 -- Entry Text{Binding A1Real} / !-- 输入框绑定 A1Real 属性 -- Picker ItemsSource{Binding A3Options} SelectedItem{Binding A3String} / !-- 下拉框绑定数据源和选中值 -- Button Command{Binding LoginCommand} / !-- 按钮绑定 Command 事件 --2. 绑定关键要求View 的 BindingContext 必须设置为对应的 ViewModel在 XAML 中设置xmlContentPage.BindingContext vm:LoginViewModel / !-- 绑定LoginViewModel -- /ContentPage.BindingContextViewModel 中的属性必须有get/set且在set中调用OnPropertyChanged()绑定的属性名必须和 ViewModel 中的属性名完全一致大小写敏感六、命令 Command按钮点击事件MVVM 模式MAUI 中按钮点击不推荐用传统的点击事件如 Click而是用「Command 命令」完全符合 MVVM 模式实现 “界面与逻辑分离”。1. 实战写法固定模板第一步ViewModel 中定义 Commandcsharp运行using System.Windows.Input; using Microsoft.Maui.Controls; public class LoginViewModel : BaseViewModel { // 定义Command public ICommand LoginCommand { get; } // 构造函数中绑定Command对应的方法 public LoginViewModel() { // 绑定LoginAsync方法按钮点击后执行 LoginCommand new Command(async () await LoginAsync()); } // Command对应的业务逻辑方法 private async Task LoginAsync() { // 登录逻辑网络请求、参数校验等 } }第二步XAML 中绑定 CommandxmlButton Text登录 Command{Binding LoginCommand} BackgroundColor#0FC97D TextColorWhite/2. 带参数的 Command修改 / 删除功能必备比如列表中的 “修改”“删除” 按钮需要传递当前选中的数据写法如下csharp运行// 带参数的Command参数类型为DataItem public ICommand DeleteCommand { get; } public ShedViewModel() { // 绑定带参数的DeleteItem方法 DeleteCommand new CommandDataItem(DeleteItem); } // 接收参数当前选中的列表项 private async void DeleteItem(DataItem item) { // 根据item.A1Real执行删除逻辑 }XAML 绑定传递当前列表项作为参数xmlButton Text删除 Command{Binding Source{x:Reference thisPage}, PathBindingContext.DeleteCommand} CommandParameter{Binding} /七、MAUI Shell 路由页面跳转核心重点Shell 是 MAUI 的路由导航系统负责管理所有页面的跳转、传参、返回我们项目中解决的 “路由报错、无法返回” 问题都和 Shell 路由相关。1. 路由注册必须在 AppShell.xaml 中配置所有需要跳转的页面都要在 AppShell.xaml 中注册路由否则无法跳转。实战示例我们项目的路由配置xmlShell x:ClassagricultureMobile.AppShell xmlns:vclr-namespace:agricultureMobile.Views Shell.FlyoutBehaviorDisabled !-- 1. 登录页启动页不放在TabBar中 -- ShellContent RouteLoginView ContentTemplate{DataTemplate v:LoginView} / !-- 2. 底部Tab页主页面 -- TabBar ShellContent Title农场2 ContentTemplate{DataTemplate v:FarmView} Iconnc_icon.png / ShellContent Title大棚 ContentTemplate{DataTemplate v:ShedView} Icondp_icon.png RouteShedView / ShellContent Title我的 ContentTemplate{DataTemplate v:MineView} Iconwd_icon.png / /TabBar !-- 3. 编辑页子页面不放在TabBar中 -- ShellContent ContentTemplate{DataTemplate v:EditView} RouteEditView/ /Shell关键规则主页面底部 Tab放在TabBar中子页面编辑页、弹窗页放在TabBar外部避免无法返回每个页面必须指定Route页面名如 RouteShedView用于跳转时定位页面2. 两种核心跳转方式重点含弹窗MAUI Shell 跳转分为「普通页面跳转」和「模态弹窗跳转」我们项目中用的是普通跳转弹窗跳转可按需扩展。方式 1普通页面跳转非弹窗最常用语法///页面路由名三个斜杠绝对路由避免报错csharp运行// 登录成功后跳转到大棚列表页普通跳转非弹窗 await Shell.Current.GoToAsync(///ShedView); // 列表页跳转到编辑页带参数传参 await Shell.Current.GoToAsync($///EditView?A1Real{item.A1Real}A2String{item.A2String});特点页面压入导航栈支持返回用..返回上一页无弹窗效果是正常的页面切换适合登录→主页、列表→编辑等场景方式 2模态弹窗跳转弹窗效果语法modal://页面路由名加 modal://弹窗形式打开csharp运行// 以弹窗形式打开编辑页 await Shell.Current.GoToAsync(modal://EditView);特点从页面底部弹出类似手机弹窗效果弹窗期间无法操作底层页面关闭弹窗返回await Shell.Current.GoToAsync(..);适合新增、编辑等需要临时打开的页面3. 路由传参与接收修改功能必备第一步跳转时传参列表→编辑页csharp运行// 传递A1Real、A2String、A3String三个参数 await Shell.Current.GoToAsync($///EditView?A1Real{item.A1Real}A2String{item.A2String}A3String{item.A3String});第二步编辑页接收参数ViewModel 中用[QueryProperty]特性接收参数自动绑定到对应的属性csharp运行using Microsoft.Maui.Controls; [QueryProperty(nameof(A1Real), nameof(A1Real))] // 接收A1Real参数 [QueryProperty(nameof(A2String), nameof(A2String))] // 接收A2String参数 [QueryProperty(nameof(A3String), nameof(A3String))] // 接收A3String参数 public class EditViewModel : BaseViewModel { private double _a1Real; private string _a2String string.Empty; private string _a3String string.Empty; // 接收的参数会自动赋值到这些属性 public double A1Real { get _a1Real; set { _a1Real value; OnPropertyChanged(); } } public string A2String { get _a2String; set { _a2String value; OnPropertyChanged(); } } public string A3String { get _a3String; set { _a3String value; OnPropertyChanged(); } } }4. 页面返回解决 “无法返回” 问题表格场景返回写法实战应用普通跳转返回上一页await Shell.Current.GoToAsync(..);编辑页返回列表页强制返回主页面await Shell.Current.GoToAsync(///ShedView);任意页面返回大棚列表页弹窗关闭await Shell.Current.GoToAsync(..);弹窗编辑页关闭返回列表页八、MAUI 网络请求HttpClient实战必备我们项目中的登录、新增、修改、删除、列表加载都用到了 HttpClient 进行网络请求这是 MAUI 中最常用的网络请求方式。1. 核心写法固定模板第一步初始化 HttpClientViewModel 中csharp运行using System.Net.Http; public class LoginViewModel : BaseViewModel { // 初始化HttpClient全局一个即可 private readonly HttpClient _httpClient new HttpClient(); // 后续所有网络请求都用这个_httpClient }第二步不同请求方式对应项目接口表格接口类型写法示例实战对应POST登录 / 新增登录await _httpClient.PostAsync(http://193.112.175.157:8001/login, content);PUT修改修改await _httpClient.PutAsync($http://193.112.175.157:8001/update/{_originalA1Real}, content);DELETE删除删除await _httpClient.DeleteAsync($http://193.112.175.157:8001/delete/{item.A1Real});GET列表加载列表var res await _httpClient.GetStringAsync(http://193.112.175.157:8001/list);第三步请求参数构造JSON 格式csharp运行using Newtonsoft.Json; using System.Text; // 1. 构造请求参数和接口入参一致 var requestObj new { username Username, password Password }; // 2. 转换为JSON字符串 var json JsonConvert.SerializeObject(requestObj); // 3. 构造请求内容指定编码和格式 var content new StringContent(json, Encoding.UTF8, application/json);九、MAUI 弹窗提示用户交互必备用于显示提示信息成功、失败、确认我们项目中登录、新增、修改、删除都用到了写法固定。1. 常用弹窗类型1提示弹窗只有确定按钮csharp运行// 格式await Shell.Current.CurrentPage.DisplayAlert(标题, 内容, 确定按钮文本); await Shell.Current.CurrentPage.DisplayAlert(成功, 删除完成, 确定);2确认弹窗确定 取消按钮用于删除、危险操作csharp运行// 格式await Shell.Current.CurrentPage.DisplayAlert(标题, 内容, 确定按钮, 取消按钮); bool confirm await Shell.Current.CurrentPage.DisplayAlert(确认删除, $确定要删除 {item.A1Real} 吗, 确定, 取消); if (confirm) { // 用户点击确定执行删除逻辑 } else { // 用户点击取消取消操作 }一、传统弹窗.NET MAUI 通用写法1. 打开弹窗csharp运行var editPage new EditView(); await Navigation.PushModalAsync(editPage);或csharp运行await Shell.Current.Navigation.PushModalAsync(new EditView());2. 关闭弹窗csharp运行await Navigation.PopModalAsync();十、MAUI 实战避坑指南新手必看结合我们项目中遇到的问题整理 10 个高频坑避免新手走弯路列表CollectionView不滚动、显示不全→ 不要放在 VerticalStackLayout 中用 Grid 布局RowDefinitionsAuto,*路由报错 “Relative routing not supported”→ 跳转用绝对路由/// 页面名不要用相对路由编辑页无法返回→ 编辑页EditView不要放在 TabBar 中放在 TabBar 外部按钮提示 “FillAndExpand 已过时”→ 用 Grid 替代 HorizontalStackLayout 实现按钮并排避免用 FillAndExpand数据绑定后界面不更新→ 忘记在 ViewModel 的属性 set 中调用 OnPropertyChanged ()路由传参接收不到→ 确保 QueryProperty 的属性名和传参名一致且属性有 get/set弹窗提示报错 “MainPage 为空”→ 用 Shell.Current.CurrentPage.DisplayAlert ()不要用 Application.Current.MainPage下拉选择框Picker无数据→ 确保 ItemsSource 绑定的集合已初始化如 ObservableCollection网络请求失败→ 检查接口地址是否正确参数格式是否为 JSON页面跳转后数据不刷新→ 跳转后手动调用列表加载方法如 LoadData ()十一、MAUI 学习路线结合我们的实战项目新手可以按以下顺序学习快速上手 MAUI基础XAML 布局Grid、StackLayout、CollectionView 等常用控件核心MVVM 模式 INotifyPropertyChanged 数据绑定进阶Shell 路由跳转、传参、返回、弹窗实战网络请求HttpClient JSON 解析扩展表单输入Entry、Picker、弹窗提示、列表增删改查优化界面美化、性能优化、避坑技巧