【Maui】下拉框的实现,绑定键值对

news2025/1/21 10:46:53

文章目录

  • 前言
  • 一、问题描述
  • 二、解决方案
  • 三、软件开发(源码)
    • 3.1 创建模型
    • 3.2 视图界面
    • 3.3 控制器逻辑层
  • 四、项目展示![在这里插入图片描述](https://i-blog.csdnimg.cn/direct/05795ee1c24c49129b822b530ef58302.png)


前言

.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 布局。

一、问题描述

MVVM模式(Model-View-ViewModel)架构模式,是将View和ViewModel关联起来,通过双向数据绑定实现View和ViewModel的同步更新。View负责展示数据和用户交互,ViewModel负责处理数据和业务逻辑,Model负责存储数据。MVVM的优点是能够降低View和ViewModel之间的耦合,使得代码更加可维护和可测试。
.NET MAUI是如何进行将View和ViewModel双向绑定的呢?

二、解决方案

1、视图–数据模型绑定:定义ViewModels,视图层通过Binding属性绑定ViewModels
2、数据模型–视图绑定:ViewModels属性发生改变,需要通知View进行更新,通知采用观察者模式,更新View采用委托Invoke
听起来很复杂对不对?其实很简单。

三、软件开发(源码)

3.1 创建模型

文件名:MO1002AddViewModel.cs
位置:ViewModels
备注:集合一定要定义成 ObservableCollection,不要使用List,否则无法实现MVVM,ObservableCollection实现INotifyCollectionChanged, INotifyPropertyChanged。

using App.Mes.Core.Entities;
using App.Mes.Core.Operation.Services.Mobile;
using Newtonsoft.Json;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Runtime.CompilerServices;

namespace GlueNet.Mobile.ViewModels
{
    public class MO1002AddViewModel : INotifyPropertyChanged
    {
        private string _mtrlTypeValue; // 物料类型
        private string _houseValue; // 线边库
        private string _bnPlantValue; // 业务工厂
        private string _reasonValue; // 原因

        public ObservableCollection<KeyValuePair<string, string>> MtrlTypeOptions { get; set; } = new ObservableCollection<KeyValuePair<string, string>>();
        public ObservableCollection<KeyValuePair<string, string>> HouseOptions { get; set; } = new ObservableCollection<KeyValuePair<string, string>>();
        public ObservableCollection<KeyValuePair<string, string>> BnPlantOptions { get; set; } = new ObservableCollection<KeyValuePair<string, string>>();
        public ObservableCollection<KeyValuePair<string, string>> ReasonOptions { get; set; } = new ObservableCollection<KeyValuePair<string, string>>();

        public KeyValuePair<string, string> MtrlTypeValue
        {
            get => new KeyValuePair<string, string>(MtrlTypeOptions.FirstOrDefault(x => x.Value == _mtrlTypeValue).Key, _mtrlTypeValue);
            set
            {
                if (_mtrlTypeValue != value.Value)
                {
                    _mtrlTypeValue = value.Value;
                    OnPropertyChanged();
                }
            }
        }

        public KeyValuePair<string, string> HouseValue
        {
            get => new KeyValuePair<string, string>(HouseOptions.FirstOrDefault(x => x.Value == _houseValue).Key, _houseValue);
            set
            {
                if (_houseValue != value.Value)
                {
                    _houseValue = value.Value;
                    OnPropertyChanged();
                }
            }
        }

        public KeyValuePair<string, string> BnPlantValue
        {
            get => new KeyValuePair<string, string>(BnPlantOptions.FirstOrDefault(x => x.Value == _bnPlantValue).Key, _bnPlantValue);
            set
            {
                if (_bnPlantValue != value.Value)
                {
                    _bnPlantValue = value.Value;
                    OnPropertyChanged();
                }
            }
        }

        public KeyValuePair<string, string> ReasonValue
        {
            get => new KeyValuePair<string, string>(ReasonOptions.FirstOrDefault(x => x.Value == _reasonValue).Key, _reasonValue);
            set
            {
                if (_reasonValue != value.Value)
                {
                    _reasonValue = value.Value;
                    OnPropertyChanged();
                }
            }
        }

        /// <summary>
        /// 构造函数
        /// </summary>
        public MO1002AddViewModel()
        {
            InitializeOptions();
        }

        private void InitializeOptions()
        {
            //物料类型初始化
            MtrlTypeOptions.Add(new KeyValuePair<string, string>("22", "纸垛"));
            MtrlTypeOptions.Add(new KeyValuePair<string, string>("23", "纸卷"));
            MtrlTypeValue = MtrlTypeOptions.FirstOrDefault();

            //线边库初始化
            string str_house = GycMobileService.Proxy.GetHouseByUser();
            var houseList = JsonConvert.DeserializeObject<List<Tax0010>>(str_house);

            foreach (var item in houseList)
            {
                HouseOptions.Add(new KeyValuePair<string, string>(item.CStoreHouse, item.CStoreHouseNm));
            }
            HouseValue = HouseOptions.FirstOrDefault();


            //业务工厂初始化
            string str_BnPlant = GycMobileService.Proxy.GetBsnsPlant();
            var BnPlantList = JsonConvert.DeserializeObject<List<Tax0002>>(str_BnPlant);

            foreach (var item in BnPlantList)
            {
                BnPlantOptions.Add(new KeyValuePair<string, string>(item.CNewBnPlantCd, item.CNewBnPlantNm));
            }
            BnPlantValue = BnPlantOptions.FirstOrDefault();

            //退库原因
            string str_Reason = GycMobileService.Proxy.GetReason();
            var ReasonList = JsonConvert.DeserializeObject<List<KeyValuePair<string, string>>>(str_Reason);
            foreach (var item in ReasonList)
            {
                ReasonOptions.Add(new KeyValuePair<string, string>(item.Key, item.Value));
            }
            ReasonValue = ReasonOptions.FirstOrDefault();
        }


        /// <summary>
        /// MO1002Page页面用,根据key获取value
        /// 备注:此方法不推荐,gyc建议服务端【联表查询】返回合适(有value)的数据对象,现在服务端ORM难以改造,故而使用此方案。
        /// </summary>
        public string GetMtrlTypeValueByKey(string key)
        {
            var house = MtrlTypeOptions.FirstOrDefault(x => x.Key == key);
            return house.Value;
        }

        public string GetHouseValueByKey(string key)
        {
            var house = HouseOptions.FirstOrDefault(x => x.Key == key);
            return house.Value;
        }

        public string GetBnPlantValueByKey(string key)
        {
            var house = BnPlantOptions.FirstOrDefault(x => x.Key == key);
            return house.Value;
        }

        public string GetReasonValueByKey(string key)
        {
            var house = ReasonOptions.FirstOrDefault(x => x.Key == key);
            return house.Value;
        }

        public event PropertyChangedEventHandler PropertyChanged;

        protected void OnPropertyChanged([CallerMemberName] string propertyName = null)
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}

3.2 视图界面

文件名:MO1002AddPage.xaml
位置:Pages
备注:第二种绑定形势,也可以在在逻辑层绑定。
<ContentPage.BindingContext>
<local:MO1002AddViewModel />
</ContentPage.BindingContext>

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="GlueNet.Mobile.Pages.MO1002AddPage"
             xmlns:local="clr-namespace:GlueNet.Mobile.ViewModels"
             Title="件次退料-制单">

    <ContentPage.BindingContext>
        <local:MO1002AddViewModel />
    </ContentPage.BindingContext>

    <VerticalStackLayout >
        <StackLayout Margin="10,20,10,20">
            <!--件次退料 制单-->
            <Frame BorderColor="LightGray" CornerRadius="5" Padding="10" Margin="5">
                <Grid ColumnDefinitions="*,*" RowDefinitions="*,*,*,*">
                    <Label Text="物料类型" VerticalOptions="Center"/>
                    <Picker Title="下拉框" Grid.Column="1" ItemsSource="{Binding MtrlTypeOptions}" SelectedItem="{Binding MtrlTypeValue}" ItemDisplayBinding="{Binding Value}"/>

                    <Label Text="线边库" Grid.Row="1" VerticalOptions="Center"/>
                    <Picker Title="下拉框" Grid.Row="1" Grid.Column="1" ItemsSource="{Binding HouseOptions}" SelectedItem="{Binding HouseValue}" ItemDisplayBinding="{Binding Value}"/>

                    <Label Text="业务工厂"  Grid.Row="2" VerticalOptions="Center"/>
                    <Picker Title="下拉框" Grid.Row="2" Grid.Column="1" ItemsSource="{Binding BnPlantOptions}" SelectedItem="{Binding BnPlantValue}" ItemDisplayBinding="{Binding Value}"/>

                    <Label Text="退库原因" Grid.Row="3" VerticalOptions="Center"/>
                    <Picker Title="下拉框" Grid.Row="3" Grid.Column="1" ItemsSource="{Binding ReasonOptions}" SelectedItem="{Binding ReasonValue}" ItemDisplayBinding="{Binding Value}"/>
                </Grid>
            </Frame>
        </StackLayout>

        <!--件次退料 制单-->
        <Grid ColumnDefinitions="*,*,*">
            <Button Grid.Column="0" HorizontalOptions="Center" VerticalOptions="Center" Text="确认"  FontSize="15" BackgroundColor="LightBlue" Clicked="OnAddClicked"/>
            <Button Grid.Column="2" HorizontalOptions="Center" VerticalOptions="Center" Text="取消"  FontSize="15" BackgroundColor="Orange" Clicked="OnCanelClicked"/>
        </Grid>

    </VerticalStackLayout>
</ContentPage>

3.3 控制器逻辑层

逻辑层代码没有,全在ViewModel构造函数中,进行了数据初始化。
逻辑如果要使用可以使用如下方法

var viewModel = BindingContext as MO1002AddViewModel;

四、项目展示在这里插入图片描述

在这里插入图片描述

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

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

相关文章

ARCGIS国土超级工具集1.3更新说明

ARCGIS国土超级工具集V1.3版本&#xff0c;功能已增加至49 个。在V1.2的基础上修复了若干使用时发现的BUG&#xff0c;完善了部分已有的功能&#xff0c;新增了“面要素狭长面检测分割”等功能&#xff0c;新工具使用说明如下&#xff1a; 一、勘测定界工具栏更新土地分类面积表…

HunyuanDiT代码笔记

HunyuanDiT 是由腾讯发布的文生图模型&#xff0c;适配中英双语。 在模型方面的改进&#xff0c;主要包括&#xff1a; transformer结构text encoderpositional encoding Improving Training Stability To stabilize training, we present three techniques: We add layer nor…

DDD - 如何设计支持快速交付的DDD技术中台

文章目录 Pre概述打造快速交付团队烟囱式的开发团队(BAD)大前端技术中台(GOOD) 技术中台的特征简单易用的技术中台建设总结 Pre DDD - 软件退化原因及案例分析 DDD - 如何运用 DDD 进行软件设计 DDD - 如何运用 DDD 进行数据库设计 DDD - 服务、实体与值对象的两种设计思路…

服务器硬盘RAID速度分析

​ 在现代数据中心和企业环境中&#xff0c;服务器的存储性能至关重要&#xff0c;RAID&#xff08;独立磁盘冗余阵列&#xff09;技术通过将多块硬盘组合成一个逻辑单元&#xff0c;提供了数据冗余和性能优化&#xff0c;本文将详细探讨不同RAID级别对服务器硬盘速度的影响&am…

【Docker】搭建一个功能强大的自托管虚拟浏览器 - n.eko

前言 本教程基于群晖的NAS设备DS423的docker功能进行搭建&#xff0c;DSM版本为 DSM 7.2.2-72806 Update 2。 n.eko 支持多种类型浏览器在其虚拟环境中运行&#xff0c;本次教程使用 Chromium​ 浏览器镜像进行演示&#xff0c;支持访问内网设备和公网地址。 简介 n.eko 是…

五、华为 RSTP

RSTP&#xff08;Rapid Spanning Tree Protocol&#xff0c;快速生成树协议&#xff09;是 STP 的优化版本&#xff0c;能实现网络拓扑的快速收敛。 一、RSTP 原理 快速收敛机制&#xff1a;RSTP 通过引入边缘端口、P/A&#xff08;Proposal/Agreement&#xff09;机制等&…

“深入浅出”系列之C++:(9)线程分离

线程分离的基本概念 线程分离是通过调用 std::thread::detach() 方法实现的。当线程被分离时&#xff0c;它会成为一个独立的线程&#xff0c;并且会自动管理自己的资源。当该线程完成执行时&#xff0c;它会自动清理资源&#xff0c;父线程不再需要等待或回收这个线程。 线程…

Day 13 卡玛笔记

这是基于代码随想录的每日打卡 144. 二叉树的前序遍历 给你二叉树的根节点 root &#xff0c;返回它节点值的 前序 遍历。 示例 1&#xff1a; 输入&#xff1a; root [1,null,2,3] 输出&#xff1a;[1,2,3] 解释&#xff1a; 示例 2&#xff1a; 输入&#xff1a; ro…

【STM32项目实战系列】系列开篇导语

【这个系列到底是什么】 简单来讲就是基于STM32的主控芯片的实际应用项目的介绍&#xff08;当然根据不同的项目功能特性需要使用不同的系列的ST主控芯片&#xff09;&#xff0c;这里面会涉及到基础工程的建立、各种驱动外设、中断和时钟的配置、RTOS的移植方法、文件系统的移…

产业园管理系统赋能企业精细管理与效益提升新路径

内容概要 现在的企业运营面临着越来越复杂的管理挑战&#xff0c;尤其是在园区管理领域。为了提升管理效率和经营效益&#xff0c;产业园管理系统的推出无疑为众多企业提供了全新的解决方案。这套系统通过智能化技术&#xff0c;将资产管理、租赁管理与财务监控等多个功能有机…

论文笔记(六十二)Diffusion Reward Learning Rewards via Conditional Video Diffusion

Diffusion Reward Learning Rewards via Conditional Video Diffusion 文章概括摘要1 引言2 相关工作3 前言4 方法4.1 基于扩散模型的专家视频建模4.2 条件熵作为奖励4.3 训练细节 5 实验5.1 实验设置5.2 主要结果5.3 零样本奖励泛化5.4 真实机器人评估5.5 消融研究 6 结论 文章…

鸿蒙中选择地区

1.首页ui import { CustomDialogExampleSelectRegion } from ./selectRegion/SelectRegionDialog;Entry Component struct Index {State selectedRegion: string 选择地区// 地区dialogControllerSelectRegion: CustomDialogController | null new CustomDialogController({b…

【HarmonyOS NAPI 深度探索12】创建你的第一个 HarmonyOS NAPI 模块

【HarmonyOS NAPI 深度探索12】创建你的第一个 HarmonyOS NAPI 模块 在本篇文章中&#xff0c;我们将一步步走过如何创建一个简单的 HarmonyOS NAPI 模块。通过这个模块&#xff0c;你将能够更好地理解 NAPI 的工作原理&#xff0c;并在你的应用中开始使用 C 与 JavaScript 的…

excel实用工具

持续更新… 文章目录 1. 快捷键1.1 求和 2. 命令2.1 查找 vloopup 1. 快捷键 1.1 求和 windows: alt mac : command shift T 2. 命令 2.1 查找 vloopup vlookup 四个入参数 要查找的内容 &#xff08;A2 6xx1&#xff09;查找的备选集 &#xff08;C2:C19&#xff09;…

Linux中的基本指令(一)

一、Linux中指令的存在意义 Linux中&#xff0c;通过输入指令来让操作系统执行&#xff0c;以此达到控制操作系统的目的&#xff0c;类似于Windows中的双击&#xff0c;右键新建文件&#xff0c;新建文件夹等 1.补&#xff1a;关于屏幕的几个操作指令 ①清屏指令 clear 回…

深入解析 C++17 中的 u8 字符字面量:提升 Unicode 处理能力

在现代软件开发中&#xff0c;处理多语言文本是一个常见需求&#xff0c;特别是在全球化的应用场景下。C17 标准引入的 u8 字符字面量为开发者提供了一个强大的工具&#xff0c;以更有效地处理和表示 UTF-8 编码的字符串。本文将详细探讨 u8 字符字面量的技术细节、实际应用&am…

2025年国产化推进.NET跨平台应用框架推荐

2025年国产化推进.NET跨平台应用框架推荐 1. .NET MAUI NET MAUI是一个开源、免费&#xff08;MIT License&#xff09;的跨平台框架&#xff08;支持Android、iOS、macOS 和 Windows多平台运行&#xff09;&#xff0c;是 Xamarin.Forms 的进化版&#xff0c;从移动场景扩展到…

C++和OpenGL实现3D游戏编程【连载21】——父物体和子物体模式实现

欢迎来到zhooyu的专栏。 &#x1f525;C和OpenGL实现3D游戏编程【专题总览】 1、本节要实现的内容 上节课我们已经创建了一个基础Object类&#xff0c;以后所有的游戏元素都可以从这个基类中派生出来。同时为了操作方便&#xff0c;我们可以为任意两个Object类&#xff08;及其…

unity插件Excel转换Proto插件-ExcelToProtobufferTool

unity插件Excel转换Proto插件-ExcelToProtobufferTool **ExcelToProtobufTool 插件文档****1. 插件概述****2. 默认配置类&#xff1a;DefaultIProtoPathConfig****属性说明** **3. 自定义配置类****定义规则****示例代码** **4. 使用方式****4.1 默认路径****4.2 自定义路径**…

【数据结构篇】顺序表 超详细!

目录 一.顺序表的定义 1.顺序表的概念及结构 1.1线性表 2.顺序表的分类 2.1静态顺序表 2.2动态顺序表 二.动态顺序表的实现 1.准备工作和注意事项 2.顺序表的基本接口&#xff1a; 2.0 创建一个顺序表 2.1 顺序表的初始化 2.2 顺序表的销毁 2.3 顺序表的打印 3.顺序…