WPF实战学习笔记24-首页编辑与完成

首页编辑与完成

  • indexview添加Listbox控件的鼠标双击行为
    • 添加todo、memo的编辑命令
    • indexviewmodel添加对应的更新事件处理
  • 添加ToggleButton与后台的绑定
    • 将ToggleButton的ischeck绑定到status属性
    • 添加bool int 转换器
    • 添加完成命令
    • 添加完成功能函数

Listbox添加行为

给行为添加命令空间

文件:Mytodo.Views.IndexView.cs

    xmlns:i="http://schemas.microsoft.com/xaml/behaviors"

添加行为事件

文件:Mytodo.Views.IndexView.cs

<i:Interaction.Triggers><i:EventTrigger EventName="MouseDoubleClick"><i:InvokeCommandAction Command="{Binding EditTodoCmd}" CommandParameter="{Binding ElementName=todolbox, Path=SelectedItem}" /></i:EventTrigger>
</i:Interaction.Triggers>
<i:Interaction.Triggers><i:EventTrigger EventName="MouseDoubleClick"><i:InvokeCommandAction Command="{Binding EditTodoCmd}" CommandParameter="{Binding ElementName=todolbox, Path=SelectedItem}" /></i:EventTrigger>
</i:Interaction.Triggers>

后台添加对应的命令,并初始化

文件:Mytodo.Views.IndexViewmodel.cs

/// <summary>
/// 命令:编辑备忘
/// </summary>
public DelegateCommand<MemoDto> EditMemoCmd { get;private set; }/// <summary>
/// 命令:编辑待办
/// </summary>
public DelegateCommand<ToDoDto> EditTodoCmd { get; private set; }
//初始化命令
EditMemoCmd = new DelegateCommand<MemoDto>(Addmemo);
EditTodoCmd = new DelegateCommand<ToDoDto>(Addtodo);

添加命令方法

文件:Mytodo.Views.IndexViewmodel.cs

/// <summary>
/// 添加待办事项
/// </summary>
async void Addtodo(ToDoDto model)
{DialogParameters param = new DialogParameters();if (model != null)param.Add("Value", model);var dialogres = await dialog.ShowDialog("AddTodoView", param);var newtodo = dialogres.Parameters.GetValue<ToDoDto>("Value");if (newtodo == null || string.IsNullOrEmpty(newtodo.Title) || (string.IsNullOrEmpty(newtodo.Content)))return;if (dialogres.Result == ButtonResult.OK){try{if (newtodo.Id > 0){var updres = await toDoService.UpdateAsync(newtodo);if (updres.Status){var todo = TodoDtos.FirstOrDefault(x=>x.Id.Equals(newtodo.Id));//更新信息todo.Content = newtodo.Content;todo.Title = newtodo.Title;todo.Status = newtodo.Status;}}else{//添加内容 //更新数据库数据var addres  = await toDoService.AddAsync(newtodo);//更新UI数据if (addres.Status){TodoDtos.Add(addres.Result);}}}catch {}finally{UpdateLoding(false);}}}/// <summary>
/// 添加备忘录
/// </summary>
async void Addmemo(MemoDto model)
{DialogParameters param = new DialogParameters();if (model != null)param.Add("Value", model);var dialogres = await dialog.ShowDialog("AddMemoView", param);if (dialogres.Result == ButtonResult.OK){try{var newmemo = dialogres.Parameters.GetValue<MemoDto>("Value");if (newmemo != null && string.IsNullOrWhiteSpace(newmemo.Content) && string.IsNullOrWhiteSpace(newmemo.Title))return;if (newmemo.Id > 0){var updres = await memoService.UpdateAsync(newmemo);if (updres.Status){//var memo = MemoDtos.FindFirst(predicate: x => x.Id == newmemo.Id);var memo = MemoDtos.FirstOrDefault( x => x.Id.Equals( newmemo.Id));//更新信息memo.Content = newmemo.Content;memo.Title = newmemo.Title;}}else{//添加内容var addres = await memoService.AddAsync(newmemo);//更新UI数据if (addres.Status){MemoDtos.Add(addres.Result);}}}catch{}finally{UpdateLoding(false);}}
}

添加ToggleButton绑定与check事件

添加转换器

添加文件:Mytodo.Common.Converters.BoolInt_TConverter.cs

using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Data;namespace Mytodo.Common.Converters
{public  class BoolInt_TConverter : IValueConverter{/// <summary>/// int to bool/// </summary>/// <param name="value"></param>/// <param name="targetType"></param>/// <param name="parameter"></param>/// <param name="culture"></param>/// <returns></returns>public object Convert(object value, Type targetType, object parameter, CultureInfo culture){if(value!=null&&int.TryParse(value.ToString(),out int result)){if(result==0)return true;elsereturn false;}return false;}/// <summary>/// bool to int /// </summary>/// <param name="value"></param>/// <param name="targetType"></param>/// <param name="parameter"></param>/// <param name="culture"></param>/// <returns></returns>public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture){if (value != null && bool.TryParse(value.ToString(), out bool result)){if (result)return 0;elsereturn 1;}return false;}}
}

添加转换器,添加命令

修改文件:Mytodo.Views.IndexView.xaml

  1. 添加命名空间
    xmlns:cv="clr-namespace:Mytodo.Common.Converters"
  1. 添加资源

        <UserControl.Resources><ResourceDictionary><cv:BoolInt_TConverter x:Key="BoolInt_TConverter" /></ResourceDictionary></UserControl.Resources>
    
  2. 绑定命令,添加转换器

    <ToggleButtonWidth="40"Command="{Binding DataContext.ToDoCompltedCommand, RelativeSource={RelativeSource Mode=FindAncestor,AncestorType=ItemsControl}}"CommandParameter="{Binding }"DockPanel.Dock="Right"IsChecked="{Binding Status, Converter={StaticResource BoolInt_TConverter}, Mode=TwoWay}" />
    <StackPanel>
    
  3. 定义命令,并初始化

    /// <summary>
    /// Todo完成命令
    /// </summary>
    public DelegateCommand<ToDoDto> ToDoCompltedCommand { get; set; }
    public IndexViewModel(IContainerProvider provider,IDialogHostService dialog) : base(provider)
    {//实例化接口this.toDoService= provider.Resolve<ITodoService>();this.memoService = provider.Resolve<IMemoService>();//实例化对象MemoDtos = new ObservableCollection<MemoDto>();TodoDtos = new ObservableCollection<ToDoDto>();//初始化命令EditMemoCmd = new DelegateCommand<MemoDto>(Addmemo);EditTodoCmd = new DelegateCommand<ToDoDto>(Addtodo);ToDoCompltedCommand = new DelegateCommand<ToDoDto>(Compete);ExecuteCommand = new DelegateCommand<string>(Execute);this.dialog = dialog;CreatBars();
    }
    
  4. 初始化命令操作函数

    /// <summary>
    /// togglebutoon 的命令
    /// </summary>
    /// <param name="dto"></param>
    /// <exception cref="NotImplementedException"></exception>
    async private void Compete(ToDoDto dto)
    {if (dto == null || string.IsNullOrEmpty(dto.Title) || (string.IsNullOrEmpty(dto.Content)))return;var updres = await toDoService.UpdateAsync(dto);if (updres.Status){var todo = TodoDtos.FirstOrDefault(x => x.Id.Equals(dto.Id));//更新信息todo.Status = dto.Status;}
    }
    

修改相关bug

修改Mytodo.ViewModels.cs

using Mytodo.Common.Models;
using Prism.Mvvm;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Reflection.Metadata;
using System.Text;
using System.Threading.Tasks;
using MyToDo.Share.Models;
using Prism.Commands;
using Prism.Services.Dialogs;
using Mytodo.Dialog;
using Mytodo.ViewModels;
using Mytodo.Service;
using Prism.Ioc;
using System.Diagnostics;
using Microsoft.VisualBasic;
using ImTools;
using DryIoc;
using MyToDo.Share;
using System.Windows;namespace Mytodo.ViewModels
{public class IndexViewModel:NavigationViewModel{#region 定义命令/// <summary>/// Todo完成命令/// </summary>public DelegateCommand<ToDoDto> ToDoCompltedCommand { get; set; }public DelegateCommand<string> ExecuteCommand { get; set; }/// <summary>/// 命令:编辑备忘/// </summary>public DelegateCommand<MemoDto> EditMemoCmd { get;private set; }/// <summary>/// 命令:编辑待办/// </summary>public DelegateCommand<ToDoDto> EditTodoCmd { get; private set; }#endregion#region 定义属性public string Title { get; set; }public ObservableCollection<MemoDto> MemoDtos{get { return memoDtos; }set { memoDtos = value; RaisePropertyChanged(); }}public ObservableCollection<ToDoDto> TodoDtos{get { return todoDtos; }set { todoDtos = value; RaisePropertyChanged(); }}/// <summary>/// 首页任务条/// </summary>public ObservableCollection<TaskBar> TaskBars{get { return taskBars; }set { taskBars = value; RaisePropertyChanged(); }}#endregion#region 定义重要命令#endregion#region 定义重要字段private readonly IDialogHostService dialog;private readonly ITodoService toDoService;private readonly IMemoService memoService;#endregion#region 定义普通字段private ObservableCollection<TaskBar> taskBars;private ObservableCollection<ToDoDto> todoDtos;private ObservableCollection<MemoDto> memoDtos;#endregion#region 命令相关方法/// <summary>/// togglebutoon 的命令/// </summary>/// <param name="dto"></param>/// <exception cref="NotImplementedException"></exception>async private void Compete(ToDoDto dto){if (dto == null || string.IsNullOrEmpty(dto.Title) || (string.IsNullOrEmpty(dto.Content)))return;var updres = await toDoService.UpdateAsync(dto);if (updres.Status){var todo = TodoDtos.FirstOrDefault(x => x.Id.Equals(dto.Id));//更新信息todo.Status = dto.Status;}}/// <summary>/// 选择执行命令/// </summary>/// <param name="obj"></param>void Execute(string obj){switch (obj){case "新增待办": Addtodo(null); break;case "新增备忘": Addmemo(null); break;}}/// <summary>/// 添加待办事项/// </summary>async void Addtodo(ToDoDto model){DialogParameters param = new DialogParameters();if (model != null)param.Add("Value", model);var dialogres = await dialog.ShowDialog("AddTodoView", param);var newtodo = dialogres.Parameters.GetValue<ToDoDto>("Value");if (newtodo == null || string.IsNullOrEmpty(newtodo.Title) || (string.IsNullOrEmpty(newtodo.Content)))return;if (dialogres.Result == ButtonResult.OK){try{if (newtodo.Id > 0){var updres = await toDoService.UpdateAsync(newtodo);if (updres.Status){var todo = TodoDtos.FirstOrDefault(x=>x.Id.Equals(newtodo.Id));//更新信息todo.Content = newtodo.Content;todo.Title = newtodo.Title;todo.Status = newtodo.Status;}}else{//添加内容 //更新数据库数据var addres  = await toDoService.AddAsync(newtodo);//更新UI数据if (addres.Status){TodoDtos.Add(addres.Result);}}}catch {}finally{UpdateLoding(false);}}}/// <summary>/// 添加备忘录/// </summary>async void Addmemo(MemoDto model){DialogParameters param = new DialogParameters();if (model != null)param.Add("Value", model);var dialogres = await dialog.ShowDialog("AddMemoView", param);if (dialogres.Result == ButtonResult.OK){try{var newmemo = dialogres.Parameters.GetValue<MemoDto>("Value");if (newmemo != null && string.IsNullOrWhiteSpace(newmemo.Content) && string.IsNullOrWhiteSpace(newmemo.Title))return;if (newmemo.Id > 0){var updres = await memoService.UpdateAsync(newmemo);if (updres.Status){//var memo = MemoDtos.FindFirst(predicate: x => x.Id == newmemo.Id);var memo = MemoDtos.FirstOrDefault( x => x.Id.Equals( newmemo.Id));//更新信息memo.Content = newmemo.Content;memo.Title = newmemo.Title;}}else{//添加内容var addres = await memoService.AddAsync(newmemo);//更新UI数据if (addres.Status){MemoDtos.Add(addres.Result);}}}catch{}finally{UpdateLoding(false);}}}#endregion#region 其它方法#endregion#region 启动项相关void CreatBars(){Title = "您好,2022";TaskBars = new ObservableCollection<TaskBar>();TaskBars.Add(new TaskBar { Icon = "CalendarBlankOutline", Title = "汇总", Color = "#FF00FF00", Content = "27", Target = "" });TaskBars.Add(new TaskBar { Icon = "CalendarMultipleCheck", Title = "已完成", Color = "#6B238E", Content = "24", Target = "" });TaskBars.Add(new TaskBar { Icon = "ChartLine", Title = "完成比例", Color = "#32CD99", Content = "100%", Target = "" });TaskBars.Add(new TaskBar { Icon = "CheckboxMarked", Title = "备忘录", Color = "#5959AB", Content = "13", Target = "" });}#endregionpublic IndexViewModel(IContainerProvider provider,IDialogHostService dialog) : base(provider){//实例化接口this.toDoService= provider.Resolve<ITodoService>();this.memoService = provider.Resolve<IMemoService>();//实例化对象MemoDtos = new ObservableCollection<MemoDto>();TodoDtos = new ObservableCollection<ToDoDto>();//初始化命令EditMemoCmd = new DelegateCommand<MemoDto>(Addmemo);EditTodoCmd = new DelegateCommand<ToDoDto>(Addtodo);ToDoCompltedCommand = new DelegateCommand<ToDoDto>(Compete);ExecuteCommand = new DelegateCommand<string>(Execute);this.dialog = dialog;CreatBars();}}
}

修改Mytodo.AddMemoViewModel.cs

using MaterialDesignThemes.Wpf;
using Mytodo.Dialog;
using MyToDo.Share.Models;
using Prism.Commands;
using Prism.Mvvm;
using Prism.Services.Dialogs;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;namespace Mytodo.ViewModels.Dialogs
{internal class AddMemoViewModel : BindableBase, IDialogHostAware{public AddMemoViewModel(){SaveCommand = new DelegateCommand(Save);CancelCommand = new DelegateCommand(Cancel);}private MemoDto model;public MemoDto Model{get { return model; }set { model = value; RaisePropertyChanged(); }}private void Cancel(){if (DialogHost.IsDialogOpen(DialogHostName))DialogHost.Close(DialogHostName, new DialogResult(ButtonResult.No));}private void Save(){if (DialogHost.IsDialogOpen(DialogHostName)){//确定时,把编辑的实体返回并且返回OKDialogParameters param = new DialogParameters();param.Add("Value", Model);DialogHost.Close(DialogHostName, new DialogResult(ButtonResult.OK, param));}}public string DialogHostName { get; set; }public DelegateCommand SaveCommand { get; set; }public DelegateCommand CancelCommand { get; set; }public void OnDialogOpend(IDialogParameters parameters){if (parameters.ContainsKey("Value")){Model = parameters.GetValue<MemoDto>("Value");if(Model == null) {Model = new MemoDto();}c}elseModel = new MemoDto();}}
}

修改Mytodo.AddTodoViewModel.cs

using MaterialDesignThemes.Wpf;
using Mytodo.Dialog;
using MyToDo.Share.Models;
using Prism.Commands;
using Prism.Mvvm;
using Prism.Services.Dialogs;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;namespace Mytodo.ViewModels.Dialogs
{internal class AddTodoViewModel : BindableBase, IDialogHostAware{public AddTodoViewModel(){SaveCommand = new DelegateCommand(Save);CancelCommand = new DelegateCommand(Cancel);}private ToDoDto model;/// <summary>/// 新增或编辑的实体/// </summary>public ToDoDto Model{get { return model; }set { model = value; RaisePropertyChanged(); }}/// <summary>/// 取消/// </summary>private void Cancel(){if (DialogHost.IsDialogOpen(DialogHostName))DialogHost.Close(DialogHostName, new DialogResult(ButtonResult.No)); //取消返回NO告诉操作结束}/// <summary>/// 确定/// </summary>private void Save(){if (DialogHost.IsDialogOpen(DialogHostName)){//确定时,把编辑的实体返回并且返回OKDialogParameters param = new DialogParameters();param.Add("Value", Model);DialogHost.Close(DialogHostName, new DialogResult(ButtonResult.OK, param));}}public string DialogHostName { get; set; }public DelegateCommand SaveCommand { get; set; }public DelegateCommand CancelCommand { get; set; }public void OnDialogOpend(IDialogParameters parameters){if (parameters.ContainsKey("Value")){Model = parameters.GetValue<ToDoDto>("Value");if (Model == null){Model = new ToDoDto();Model.Status = 1;}}else{Model = new ToDoDto();Model.Status = 1;}}}
}

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

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

相关文章

C语言假期作业 DAY 01

题目 1.选择题 1、执行下面程序&#xff0c;正确的输出是&#xff08; &#xff09; int x5,y7; void swap() { int z; zx; xy; yz; } int main() { int x3,y8; swap(); printf("%d,%d\n"&#xff0c;x, y)…

Android Studio 代码模板插件实现

Android Studio 代码模板插件 背景 可以跳过背景和简述&#xff0c;从模板插件实现开始看. 开发新页面时&#xff0c;原先需要写一堆模板代码。比如用Databinding写列表结构的页面&#xff0c;需要手写以下文件&#xff1a; XxActivity.ktXxFragment.ktXxViewModel.ktXxListA…

一、SpringBoot基础[日志]

一、日志 解释&#xff1a;SpringBoot使用logback作为默认的日志框架&#xff0c;其中还可以导入log4j2等优秀的日志框架 1.修改日志内容 修改整个日志格式&#xff1a;logging.pattern.console%d{yyyy-MM-dd HH:mm:ss} %-5level [%thread] %logger{15} 你好 %msg%n %d{yyy…

基于K8s环境·使用ArgoCD部署Jenkins和静态Agent节点

今天是「DevOps云学堂」与你共同进步的第 47天 第⑦期DevOps实战训练营 7月15日已开营 实践环境升级基于K8s和ArgoCD 本文节选自第⑦期DevOps训练营 &#xff0c; 对于训练营的同学实践此文档依赖于基础环境配置文档&#xff0c; 运行K8s集群并配置NFS存储。实际上只要有个K8s集…

CAD .NET 15.0 企业版 Crack

CAD .NET 15.0 企业版 企业版 企业版 企业版 企业版 Updated: June 14, 2023 | Version 15.0 NEW CAD .NET is a library for developing solutions in .NET environment. It supports AutoCAD DWG/ DXF, PLT and other CAD formats. The library can be used in a wide rang…

C语言之pthread_cond_t信号变化探究总结(八十)

简介&#xff1a; CSDN博客专家&#xff0c;专注Android/Linux系统&#xff0c;分享多mic语音方案、音视频、编解码等技术&#xff0c;与大家一起成长&#xff01; 优质专栏&#xff1a;Audio工程师进阶系列【原创干货持续更新中……】&#x1f680; 人生格言&#xff1a; 人生…

【RabbitMQ(day2)】默认(直连)交换机的应用

文章目录 一、第一种模型&#xff08;Hello World&#xff09;二、第二种模型&#xff08;work queue&#xff09;自动确认机制的后果和公平分配 三、阐述默认交换机 这篇博客是以下资料学后的总结&#xff1a; 不良人的RabbitMQ的教学视频 官方启动教程 RabbitMQ中文文档 一、…

基于TCP/IP对等模型对计算机网络知识点的整合

目录 前言 应用层 Telnet SSH FTP/TFTP SNMP&#xff1a;简单的网络管理协议 HTTP&#xff1a;超文本传输协议 SMTP&#xff1a;电子邮件传输协议 DNS&#xff1a;域名解析协议 DHCP&#xff1a;动态主机配置协议 NTP&#xff1a;网络时钟协议 传输层 TCP UDP 端…

【SQL语句】

目录 一、SQL语句类型 1.DDL 2.DML 3.DLL 4.DQL 二、数据库操作 1.查看 2.创建 2.1 默认字符集 2.2 指定字符集 3.进入 4.删除 5.更改 5.1 库名称 5.2 字符集 三、数据表操作 1.数据类型 1.1 数值类型&#xff08;常见&#xff0c;下同&#xff09; 1.1.1 T…

ChatGPT长文本对话输入方法

ChatGPT PROMPTs Splitter 是一个开源工具&#xff0c;旨在帮助你将大量上下文数据分成更小的块发送到 ChatGPT 的提示&#xff0c;并根据如何处理所有块接收到 ChatGPT&#xff08;或其他具有字符限制的语言模型&#xff09;的方法。 推荐&#xff1a;用 NSDT设计器 快速搭建可…

【QT】Day3

1. 完成闹钟的实现&#xff1a; widgt.h #ifndef WIDGET_H #define WIDGET_H#include <QWidget> #include <QDebug> #include <QTimerEvent> //定时器事件处理函数 #include <QTime> //时间类 #include <QTextToSpeech> //文本转语音类头…

Jmap-JVM(十六)

上篇文章说了ZGC是jdk11加入的&#xff0c;他是未来jvm垃圾收集器的奠定者&#xff0c;满足TB级别内存处理&#xff0c;STW时间保持在10ms以下。 Jmap 我们可以先通过jmap -histo 进程ip 来查看&#xff0c;但是这样看不太清晰&#xff0c;我们可以用这行命令生成一个文件&…

机器学习:GPT3

GPT3 模型过于巨大 GPT3是T5参数量的10倍&#xff01; 训练GPT3的代价是$12百万美元 Zero-shot Ability GPT3的思想是不是能拿掉Fine-tune 只需要给定few-shot或者zero-shot就能干相应的任务了。 few-shot learning&#xff08;no gradient descent&#xff09;&#…

数据结构---栈

(一)栈之基础补充 C语言内存分配 对于一个C语言程序而言,内存空间主要由五个部分组成 代码段(text)、数据段(data)、未初始化数据段(bss),堆(heap) 和 栈(stack) 组成,其中代码段,数据段和BSS段是编译的时候由编译器分配的,而堆和栈是程序运行的时候由系统分配的。布局如…

生命在于折腾——面试问题汇总

这里面的问题都是我参加面试时候遇到的问题&#xff0c;大家就这样看吧。 一、个人情况 1、自我介绍 2、为什么离开上一家公司 3、有没有参加过HVV 4、介绍一下上家公司的项目 5、小程序和公众号渗透测试做过么 6、实习工资多少 7、有挖过漏洞么 二、基础知识 1、信息收集的…

遇到本地跨域问题时候webpack本地开发配置proxy的方式

if (location.host.indexOf("localhost") ! -1) {baseUrl IP /pc /cfsm;} else {//这里不许改&#xff0c;谁改谁请30杯奶茶&#xff0c;并且罚款500baseUrl ""; } const api {user: baseUrl "/web-user",excel: baseUrl "/web-exce…

【Java框架】RPC远程调用

RPC架构 一、RPC概述 RPC&#xff08;Remote Procedure Call&#xff09;叫作远程过程调用&#xff0c;它是利用网络从远程计算机上请求服务&#xff0c;可以理解为把程序的一部分放在其他远程计算机上执行。通过网络通信将调用请求发送至远程计算机后&#xff0c;利用远程计…

9.python设计模式【外观模式】

内容&#xff1a;为子系统中的一组接口提供一个一致的界面&#xff0c;外观模式定义了一个高层接口&#xff0c;这个接口使得这一个子系统更加容易使用。 角色&#xff1a; 外观&#xff08;facade&#xff09;子类系统&#xff08;subsystem classes&#xff09; UML图 举…

容器化安装环境EFK搭建

容器化安装环境 Docker中安装并启动ElasticSearch 前置配置 第一步&#xff1a;在宿主机上执行echo “net.ipv4.ip_forward1” >>/usr/lib/sysctl.d/00-system.conf 2.第二步&#xff1a;重启network和docker服务 [rootlocalhost /]# systemctl restart network &&…

使用低代码开发,需要注意哪些?

低代码平台的历史相对较短&#xff0c;大约始于 2000 年初&#xff0c;源于快速应用程序开发工具。随着低代码平台和工具的日益普及和优势&#xff0c;它不断发展以满足各种领域和角色的需求。 本文将研究各种低代码和无代码应用程序开发方法、业务用例、挑战和未来预测等。 一…