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

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

文章目录

  • 前言
  • 一、问题描述
  • 二、解决方案
  • 三、软件开发(源码)
    • 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.kler.cn/a/511970.html

相关文章:

  • OpenCV简介、OpenCV安装
  • 语音技术在播客领域的应用(2)
  • 回归算法、聚类算法、决策树、随机森林、神经网络
  • Vue 3 自定义 Hook:实现页面数据刷新与滚动位置还原
  • 1.写在前面
  • OpenMP并行编程实例系列2 —— 并行结构
  • 【HarmonyOS NAPI 深度探索12】创建你的第一个 HarmonyOS NAPI 模块
  • [计算机网络]一. 计算机网络概论第一部分
  • 04商品详情
  • react中,使用antd的Upload组件切片上传.zip文件及压缩包的下载
  • PyTorch使用教程(15)-常用开源数据集简介
  • 【STM32-学习笔记-15-】MAX7219点阵屏模块
  • Redis - General - 未授权访问漏洞(用户配置问题)
  • Quartus:开发使用及 Tips 总结
  • 适合快递驿站出库仪一体机的安卓主板
  • 如何在龙蜥 OS(AliOS)上安装极狐GitLab?
  • canvas snake game
  • 面向CTF的python_requests库的学习笔记
  • 二十项零信任相关的前沿和趋势性技术-Extranet as a Service
  • 中国综合算力指数(2024年)报告汇总PDF洞察(附原数据表)
  • C#集合排序指南:掌握自定义排序的多种方法
  • 汇编学习笔记(自用)
  • LLM(3) : 浏览器录制16K的音频并上传到后端
  • UG NX二次开发(C#)-创建三维直线段并倒圆
  • 研1如何准备才能找到大厂实习?
  • Sudo命令的配置及使用