【Maui】动态菜单实现(绑定数据视图)

前言

.NET 多平台应用 UI (.NET MAUI) 是一个跨平台框架,用于使用 C# 和 XAML 创建本机移动和桌面应用。
使用 .NET MAUI,可从单个共享代码库开发可在 Android、iOS、macOS 和 Windows 上运行的应用。

.NET MAUI 是一款开放源代码应用,是 Xamarin.Forms 的进化版,从移动场景扩展到了桌面场景,并从头重新生成了 UI 控件,以提高性能和可扩展性。 如果以前使用过 Xamarin.Forms 来生成跨平台用户界面,那么你会注意到它与 .NET MAUI 有许多相似之处。 但也有一些差异。 通过使用 .NET MAUI,可使用单个项目创建多平台应用,但如果有必要,可以添加特定于平台的源代码和资源。 .NET MAUI 的主要目的之一是使你能够在单个代码库中实现尽可能多的应用逻辑和 UI 布局。

一、问题描述

实现如下效果,菜单根据数据库取数,自动加载。
在这里插入图片描述

二、解决方案

创建数据模型
UserMenu.cs 用户功能菜单,功能字、导航页面名(后面使用反射可以实例化窗体)、图标名。
UserMenu.cs 用户模块菜单,模块下挂在用户功能菜单。
MenuService.cs 业务逻辑单元,相应事件的处理,菜单数据初始化

三、详细代码

3.1 创建用户菜单模型

二级菜单,功能级别的,UserMenu.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Input;namespace GlueNet.Mobile.Models
{public class UserMenu{/// <summary>/// 功能名/// </summary>public string Name { get; set; }/// <summary>/// 图标名/// </summary>public string Icon { get; set; }/// <summary>/// 路由名/// </summary>public string Router { get; set; }/// <summary>/// 命令/// </summary>public ICommand Command { get; set; }}
}

3.2 创建用户菜单视图模型

一级菜单,模块级别的,观察者模式需要变更属性,UserMenuViewModel.cs

using GlueNet.Mobile.Models;
using System.ComponentModel;
using System.Runtime.CompilerServices;namespace GlueNet.Mobile.ViewModels
{/// <summary>/// 实现INotifyPropertyChanged接口,观察者模式/// 属性改变通知绑定控件更新/// </summary>public class UserMenuViewModel : INotifyPropertyChanged{/// <summary>/// 模块名/// </summary>private string _moduleName;/// <summary>/// 功能集合/// </summary>private List<UserMenu> _functions;/// <summary>/// 是否展开/// </summary>private bool _isExpanded;/// <summary>/// 展开/收起文本/// </summary>private string _expandedText;public string ModuleName{get => _moduleName;set{_moduleName = value;OnPropertyChanged();}}public List<UserMenu> Functions{get => _functions;set{_functions = value;OnPropertyChanged();}}public bool IsExpanded{get => _isExpanded;set{_isExpanded = value;OnPropertyChanged();}}public string ExpandedText{get => _expandedText;set{_expandedText = value;OnPropertyChanged();}}public event PropertyChangedEventHandler PropertyChanged;protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null){PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));}}
}

3.3 创建用户菜单服务方法

绑定事件、菜单数据初始化。

using GlueNet.Bussiness.Dtos;
using GlueNet.Bussiness;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Collections.ObjectModel;
using System.ServiceModel.Channels;
using System.Windows.Input;
using GlueNet.Mobile.ViewModels;
using GlueNet.Mobile.Models;
using static System.Runtime.InteropServices.JavaScript.JSType;
using System.Xml.Linq;
using System.Diagnostics.Metrics;namespace GlueNet.Mobile.BLL
{public class MenuService : BindableObject{public ObservableCollection<UserMenuViewModel> MenuGroups { get; set; }public ICommand ToggleExpandCommand { get; protected set; }public MenuService(){ToggleExpandCommand = new Command<UserMenuViewModel>(OnToggleExpand);GetMenuData();}private void OnToggleExpand(UserMenuViewModel menuGroup){if (menuGroup != null){menuGroup.IsExpanded = !menuGroup.IsExpanded;menuGroup.ExpandedText = menuGroup.IsExpanded ? "收起" : "展开";OnPropertyChanged(nameof(MenuGroups));}}/// <summary>/// 获取菜单数据,从MES服务端获取/// </summary>public void GetMenuData(){MenuGroups = new ObservableCollection<UserMenuViewModel>{new UserMenuViewModel{ModuleName = "质量管理",Functions = new List<UserMenu>{new UserMenu { Name = "质量1", Icon = "icon_quality.png", Router ="MO2001Page", Command = new Command(() => NavigateToPage("MO2001Page")) } ,new UserMenu { Name = "质量2", Icon = "icon_quality.png", Router = "MO2001Page",Command = new Command(() => NavigateToPage("MO2001Page")) },new UserMenu { Name = "质量3", Icon = "icon_quality.png", Router = "MO2001Page" ,Command = new Command(() => NavigateToPage("MO2001Page"))},new UserMenu { Name = "质量4", Icon = "icon_quality.png", Router = "MO2001Page" ,Command = new Command(() => NavigateToPage("MO2001Page"))},new UserMenu { Name = "质量5", Icon = "icon_quality.png", Router = "MO2001Page" ,Command = new Command(() => NavigateToPage("MO2001Page"))},new UserMenu { Name = "质量6", Icon = "icon_quality.png", Router = "MO2001Page" ,Command = new Command(() => NavigateToPage("MO2001Page"))},new UserMenu { Name = "质量7", Icon = "icon_quality.png", Router = "MO2001Page" ,Command = new Command(() => NavigateToPage("MO2001Page"))},new UserMenu { Name = "质量8", Icon = "icon_quality.png", Router = "MO2001Page" ,Command = new Command(() => NavigateToPage("MO2001Page"))},new UserMenu { Name = "质量9", Icon = "icon_quality.png", Router = "MO2001Page" ,Command = new Command(() => NavigateToPage("MO2001Page"))},},IsExpanded = true,ExpandedText = "收起"},new UserMenuViewModel{ModuleName = "采购管理",Functions = new List<UserMenu>{new UserMenu { Name = "采购1", Icon = "icon_supply.png", Router="MO2001Page", Command = new Command(() => NavigateToPage("MO2001Page")) } ,new UserMenu { Name = "采购2", Icon = "icon_supply.png", Router = "MO2001Page",Command = new Command(() => NavigateToPage("MO2001Page")) },new UserMenu { Name = "采购3", Icon = "icon_supply.png", Router = "MO2001Page" ,Command = new Command(() => NavigateToPage("MO2001Page"))},},IsExpanded = true,ExpandedText = "收起"},new UserMenuViewModel{ModuleName = "作业管理",Functions = new List<UserMenu>{new UserMenu { Name= "栈板下线", Icon= "icon_operation.png", Router="MO1001Page",Command = new Command(() => NavigateToPage("MO1001Page"))},new UserMenu { Name = "次件退库", Icon = "icon_operation.png", Router = "MO1002Page",Command = new Command(() => NavigateToPage("MO1002Page")) }},IsExpanded = true,ExpandedText = "收起"}};}/// <summary>/// 使用反射,根据页面名称导航到指定页面/// </summary>/// <param name="pageName"></param>/// <exception cref="ArgumentException"></exception>private async void NavigateToPage(string pageName){// 获取对象名Type pageType = Type.GetType($"GlueNet.Mobile.Pages.{pageName}");if (pageType != null){//创建实例Page page = (Page)Activator.CreateInstance(pageType);await Application.Current.MainPage.Navigation.PushAsync(page);}else{throw new ArgumentException($"无法导航页面: {pageName}");}}}
}

3.4 创建用户菜单界面

xaml前段界面,需要使用模型绑定,和CollectionView遍历,创建MenuView.xaml。

<?xml version="1.0" encoding="utf-8" ?>
<ContentView xmlns="http://schemas.microsoft.com/dotnet/2021/maui"xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"xmlns:local="clr-namespace:GlueNet.Mobile.BLL"x:Class="GlueNet.Mobile.MenuView"><!--绑定上下文--><ContentView.BindingContext><local:MenuService /></ContentView.BindingContext><!--绑定字体资源,图标已经生成字体库--><ContentView.Resources><Style x:Key="NavButtonStyle" TargetType="RadioButton"><Setter Property="ControlTemplate"><ControlTemplate><Grid><Grid.RowDefinitions><RowDefinition/><RowDefinition Height="30" /></Grid.RowDefinitions><!--替换为图标--><Label Text="{TemplateBinding Value}" FontFamily="Iconfont" FontSize="30" HorizontalOptions="Center"VerticalOptions="Center"></Label><!--替换为文字--><Label Text="{TemplateBinding Content}" Grid.Row="1" HorizontalOptions="Center"VerticalOptions="Center" FontSize="13"></Label></Grid></ControlTemplate></Setter></Style></ContentView.Resources><ScrollView><StackLayout><CollectionView ItemsSource="{Binding MenuGroups}"><CollectionView.ItemTemplate><DataTemplate><StackLayout><!-- 模块名 --><Frame BorderColor="Gray" CornerRadius="5" Padding="5" Margin="5"><Grid ColumnDefinitions="*,60"><Label Text="{Binding ModuleName}" FontSize="Medium" FontAttributes="Bold" VerticalTextAlignment="Center"/><Button Grid.Column="1" Text="{Binding ExpandedText}" Command="{Binding Source={RelativeSource AncestorType={x:Type local:MenuService}}, Path=ToggleExpandCommand}" CommandParameter="{Binding .}" /></Grid></Frame><!-- 功能列表 --><StackLayout IsVisible="{Binding IsExpanded}"><CollectionView ItemsSource="{Binding Functions}" ItemsLayout="VerticalGrid,4"><CollectionView.ItemTemplate><DataTemplate><Grid Padding="5"><Grid.RowDefinitions><RowDefinition Height="*" /><RowDefinition Height="Auto" /></Grid.RowDefinitions><Frame BorderColor="LightGray" CornerRadius="5" Padding="10" Margin="5"><StackLayout Orientation="Vertical" HorizontalOptions="Center" VerticalOptions="Center" ><ImageButton Source="{Binding Icon}" HorizontalOptions="Center" Command="{Binding Command}" /><Label Text="{Binding Name}" FontSize="Medium" VerticalOptions="Center" HorizontalOptions="Center" Margin="10,0,0,0" /></StackLayout></Frame></Grid></DataTemplate></CollectionView.ItemTemplate></CollectionView></StackLayout></StackLayout></DataTemplate></CollectionView.ItemTemplate></CollectionView></StackLayout></ScrollView>
</ContentView>

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/65945.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Bash语言的语法糖

Bash语言的语法糖 引言 在现代编程语言中&#xff0c;“语法糖”是一个非常常见的术语&#xff0c;它指的是那些使代码更加易读、易写的语法特性。尽管这些特性并不改变语言的功能&#xff0c;但它们能显著提升开发者的编程体验。在众多编程语言中&#xff0c;Bash&#xff0…

linux---Nginx详细教程(包含安装,网站部署)

Nginx是一个高性能的HTTP和反向代理服务器&#xff0c;也可以用作邮件代理服务器&#xff0c;其以占有内存少、并发能力强、稳定性高、丰富的功能集、低系统资源消耗而闻名。以下是对Nginx的详细教程&#xff1a; 一、Nginx简介 Nginx由俄罗斯人开发&#xff0c;第一个公开版…

RNN之:LSTM 长短期记忆模型-结构-理论详解-及实战(Matlab向)

0.前言 递归&#xff01;循环神经网络Recurrent Neural Network 循环神经网络&#xff08;又称递归神经网络&#xff0c;Recurrent Neural Network&#xff0c;RNN&#xff09;。是一种用于处理序列数据的神经网络结构&#xff0c;具有记忆功能&#xff0c;能够捕捉序列中的时…

泛目录和泛站有什么差别

啥是 SEO 泛目录&#xff1f; 咱先来说说 SEO 泛目录是啥。想象一下&#xff0c;你有一个巨大的图书馆&#xff0c;里面的书架上摆满了各种各样的书&#xff0c;每一本书都代表着一个网页。而 SEO 泛目录呢&#xff0c;就像是一个超级图书管理员&#xff0c;它的任务就是把这些…

初识@ffmpeg/ffmpeg库

前言 FFmpeg是一套可以用来记录、转换数字音频、视频,并且能够利用它们来创建一个新的流媒体格式的自由软件项目,它被广泛应用在视频处理、音频处理以及直播领域。其中,@ffmpeg/ffmpeg 是一个将 FFmpeg 编译为 WebAssembly(WASM)的库,可支持几乎所有的音视频格式。 安装…

【图像去噪】论文复现:反向扩散中加入MAP将扩散模型从高斯去噪推广到真实去噪!DiffusionVI的Pytorch源码复现,跑通源码,梳理理论,单卡可执行!

请先看【专栏介绍文章】:【图像去噪(Image Denoising)】关于【图像去噪】专栏的相关说明,包含适配人群、专栏简介、专栏亮点、阅读方法、定价理由、品质承诺、关于更新、去噪概述、文章目录、资料汇总、问题汇总(更新中) 完整代码和训练好的模型权重文件下载链接见本文底…

Windows 蓝牙驱动开发-简介

蓝牙(英语&#xff1a;Bluetooth)是一种无线通信技术标准&#xff0c;用来让固定与移动设备&#xff0c;在短距离间交换资料&#xff0c;以形成个人局域网(PAN)。其使用短波特高频(UHF)无线电波&#xff0c;经由2.4至2.485 GHz的ISM频段来进行通信。1994年由电信商爱立信(Erics…

【Vue】全局/局部组件使用流程(Vue2为例)

全局组件和局部组件区别 如何使用 全局组件&#xff1a;全局注册后&#xff0c;可以在任意页面中直接使用。局部组件&#xff1a;在页面中需要先导入子组件路径&#xff0c;注册组件才能使用。 适用场景 全局组件&#xff1a;适用于高频使用的组件&#xff0c;如导航栏、业…

【Pytorch实用教程】PyTorch 中如何输出模型参数:全面指南

文章目录 PyTorch 中如何输出模型参数:全面指南1. 为什么需要输出模型参数?2. PyTorch 中输出模型参数的方法2.1 使用 `model.parameters()` 输出所有参数2.2 使用 `model.named_parameters()` 输出参数名称和值2.3 使用 `model.state_dict()` 输出模型的参数字典2.4 输出特定…

vscode vue 自动格式化

vscode vue 自动格式化 安装Prettier和Vetur插件 选择设置&#xff0c;并且转到编辑文件。增加如下内容。 {"editor.formatOnSave": true,"editor.defaultFormatter": "esbenp.prettier-vscode","[vue]": {"editor.defaultFor…

1、docker概念和基本使用命令

docker概念 微服务&#xff1a;不再是以完整的物理机为基础的服务软件&#xff0c;而是借助于宿主机的性能。以小量的形式&#xff0c;单独部署的应用。 docker&#xff1a;是一个开源的应用容器引擎&#xff0c;基于go语言开发的&#xff0c;使用时apache2.0的协议。docker是…

Genymotion配套VirtualBox所在地址

在 Genymotion打开虚拟机前需要先打开VirtualBox中的虚拟机 C:\Program Files\Oracle\VirtualBox\VirtualBox.exe 再开启genymotion中的虚拟机开关

【Linux】深刻理解软硬链接

一.软硬链接操作 1.软连接 touch 创建一个文件file.txt &#xff0c;对该文件创建对应的软链接改怎么做呢&#xff1f; ln -s file.txt file-soft.link .给对应文件创建软连接。 软连接本质就是一个独立的文件&#xff0c;因为我们对应的软连接有独立的inode&#xff0c;他…

linux下MySQL的数据存放

在 Linux 下安装的 MySQL&#xff0c;数据表的数据默认存放在 My晓SQL 数据库的**数据目录**&#xff08;Data Directory&#xff09;中。具体来说&#xff0c;MySQL 会将所有数据库的数据存储在一个由 MySQL 配置文件中指定的目录里。该目录包含了所有数据库的表、索引、日志等…

第三十六章 Spring之假如让你来写MVC——拦截器篇

Spring源码阅读目录 第一部分——IOC篇 第一章 Spring之最熟悉的陌生人——IOC 第二章 Spring之假如让你来写IOC容器——加载资源篇 第三章 Spring之假如让你来写IOC容器——解析配置文件篇 第四章 Spring之假如让你来写IOC容器——XML配置文件篇 第五章 Spring之假如让你来写…

快速上手 HarmonyOS 应用开发

一、DevEco Studio 安装与配置 1. DevEco Studio 简介 DevEco Studio 是 HarmonyOS 的一站式集成开发环境&#xff08;IDE&#xff09;&#xff0c;提供了丰富的工具和功能&#xff0c;支持 HarmonyOS 应用开发的全流程。 2. DevEco Studio 下载与安装 下载地址&#xff1a…

Java Web开发进阶——错误处理与日志管理

错误处理和日志管理是任何生产环境中不可或缺的一部分。在 Spring Boot 中&#xff0c;合理的错误处理机制不仅能够提升用户体验&#xff0c;还能帮助开发者快速定位问题&#xff1b;而有效的日志管理能够帮助团队监控应用运行状态&#xff0c;及时发现和解决问题。 1. 常见错误…

图解Git——分支的新建与合并《Pro Git》

⭐分支的新建与合并 先引入一个实际开发的工作流&#xff1a; 开发某个网站。为实现某个新的需求&#xff0c;创建一个分支。在这个分支上开展工作。 正在此时&#xff0c;你突然接到一个电话说有个很严重的问题需要紧急修补。你将按照如下方式来处理&#xff1a; 切换到你…

C#使用实体类Entity Framework Core操作mysql入门:从数据库反向生成模型2 处理连接字符串

初级代码游戏的专栏介绍与文章目录-CSDN博客 我的github&#xff1a;codetoys&#xff0c;所有代码都将会位于ctfc库中。已经放入库中我会指出在库中的位置。 这些代码大部分以Linux为目标但部分代码是纯C的&#xff0c;可以在任何平台上使用。 源码指引&#xff1a;github源…

【数据可视化-12】数据分析岗位招聘分析

&#x1f9d1; 博主简介&#xff1a;曾任某智慧城市类企业算法总监&#xff0c;目前在美国市场的物流公司从事高级算法工程师一职&#xff0c;深耕人工智能领域&#xff0c;精通python数据挖掘、可视化、机器学习等&#xff0c;发表过AI相关的专利并多次在AI类比赛中获奖。CSDN…