C# WPF上位机开发(会员管理软件)

【 声明:版权所有,欢迎转载,请勿用于商业用途。 联系信箱:feixiaoxing @163.com】

        好多同学都认为上位机只是纯软件开发,不涉及到硬件设备,比如听听音乐、看看电影、写写小的应用等等。如果是消费电子,确实可能是这种情况。但是除了消费电子、互联网领域之外,上位机还可能涉及到工业生产、医疗和军工领域,每一个细分市场都有很大的规模。这个时候,上位机就可能需要通过USB、can、232、485、网络等很多cabel形式和外部设备进行沟通,那么上位机的功能边际就会一下子拓展很多。此外,就算是同一个领域,不同的行业也都会有不同的know-how,很多的know-how就是以软件的形式固化在软件逻辑里面的,这就是上位机真正的竞争力。

        当然说了这么多,今天我们还是从简单的会员管理软件说起。通俗一点说,它就是简单的学生管理系统。所以的文件需要保存到一个文本里面,通常可以认为是json形式。软件启动后,界面可以完成增删改查的操作。当然,我们可以说增删改查不是那么高端,但它确实软件开发很基础的一个环节。

1、确定文件保存的形式,比如data.json

{"count": 6,"items": [{"ID": 1,"NAME": "aaa"},{"ID": 2,"NAME": "bbb"},{"ID": 3,"NAME": "ccc"},{"ID": 5,"NAME": "ddd"},{"ID": 6,"NAME": "eee"},{"ID": 4,"NAME": "fff"}]
}

        目前如果不用数据库的话,比较方便数据读取和保存的方式就是json格式。如上图所示,这里包含了数据的基本信息,包括了数据的数量,每一组数据的ID和NAME等等。

2、使用Newtonsoft.Json库读写json文件

        前面我们决定用json格式读写文件,接下来需要面对的问题就是如何解析和保存这些数据。好在NuGet上面可以通过第三方库Newtonsoft.Json来直接解析json文件,这就变得非常方便了。

3、设计界面

        界面部分的设计不难。简单一点难说,可以分成两个部分。左边就是数据的增删改查工作,右边就是当前所有数据的显示部分。之所以要添加右边这部分显示内容,主要还是为了直观地去观察,我们当前的操作有没有问题。

        设计好界面之后,再转成xaml代码就不难了,

<Window x:Class="WpfApp.MainWindow"xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"xmlns:d="http://schemas.microsoft.com/expression/blend/2008"xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"xmlns:local="clr-namespace:WpfApp"mc:Ignorable="d"Title="MemberInfo" Height="300" Width="800"><Grid><RadioButton x:Name="radio_add" Checked="Add_Checked" Content="add" HorizontalAlignment="Left" Margin="51,44,0,0" VerticalAlignment="Top"/><RadioButton x:Name="radio_del" Checked="Del_Checked" Content="del" HorizontalAlignment="Left" Margin="129,44,0,0" VerticalAlignment="Top"/><RadioButton x:Name="radio_update" Checked="Update_Checked" Content="update" HorizontalAlignment="Left" Margin="194,44,0,0" VerticalAlignment="Top"/><RadioButton x:Name="radio_search" Checked="Search_Checked" Content="search" HorizontalAlignment="Left" Margin="284,44,0,0" VerticalAlignment="Top"/><Label Content="ID:" HorizontalAlignment="Left" Margin="75,97,0,0" VerticalAlignment="Top"/><TextBox x:Name="id" HorizontalAlignment="Left" Height="23" Margin="193,97,0,0" TextWrapping="Wrap" Text="" VerticalAlignment="Top" Width="120"/><Label Content="Name" HorizontalAlignment="Left" Margin="75,134,0,0" VerticalAlignment="Top"/><TextBox x:Name="name" HorizontalAlignment="Left" Height="23" Margin="193,138,0,0" TextWrapping="Wrap" Text="" VerticalAlignment="Top" Width="120" RenderTransformOrigin="0.498,2.609"/><Button Content="OK" Click="OK_Click" HorizontalAlignment="Left" Margin="51,202,0,0" VerticalAlignment="Top" Width="75"/><Button Content="Cancel" Click="Cancel_Click" HorizontalAlignment="Left" Margin="157,202,0,0" VerticalAlignment="Top" Width="75"/><Button Content="Save" Click="Save_Click" HorizontalAlignment="Left" Margin="263,202,0,0" VerticalAlignment="Top" Width="75"/><Label Content="Member Details" HorizontalAlignment="Left" Margin="435,38,0,0" VerticalAlignment="Top"/><TextBox x:Name="all_data" HorizontalAlignment="Left" Height="146" Margin="435,75,0,0" TextWrapping="Wrap" Text="" VerticalAlignment="Top" Width="315"/><Border BorderBrush="Black" BorderThickness="1" HorizontalAlignment="Left" Height="235" Margin="395,10,0,0" VerticalAlignment="Top" Width="376"/><Border BorderBrush="Black" BorderThickness="1" HorizontalAlignment="Left" Height="235" Margin="15,10,0,0" VerticalAlignment="Top" Width="360"/></Grid>
</Window>

        软件部分的控件都是常见的控件,比如RadioButton、Label、TextBox、Button,同时为了进行左右区别,我们还额外添加了一个Boarder,这样稍微美观一点。

4、代码编写

        代码整体上难度不大,最重要的就是OK按钮的处理,因为它需要判断下当前是哪一种操作模式,是添加,还是其他的操作模式。每一种操作模式的处理逻辑也是不一样的。这部分内容大家可以直接查看OK_Click的函数内容。

        除了OK按钮的处理之外,另外比较重要的代码,就是json文件的加载和保存。加载是在软件启动的时候自动加载的,而保存则需要用户单击Save按钮才会自动保存。

        最后大家可以关注下update_data这个函数,只要是正常的操作,数据内容发生变化,都会调用这个函数更新Textbox里面的内容。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;using Newtonsoft.Json;
using Newtonsoft.Json.Linq;namespace WpfApp
{/// <summary>/// MainWindow.xaml 的交互逻辑/// </summary>public partial class MainWindow : Window{private int select_option = 0;private int total = 0;private int[] id_array = new int[1000];private string[] name_array = new string[1000];public MainWindow() // construct function{InitializeComponent();// initialize datafor(int i = 0; i < 1000;i++){id_array[i] = 0;name_array[i] = "";}// load file defined hereload_file();radio_add.IsChecked = true; // set as default value//display data hereall_data.Text = "";all_data.IsEnabled = false;update_data();}private void load_file(){string jsonfile = "data.json";JObject jObject;JToken items;// parse script fileusing (System.IO.StreamReader file = System.IO.File.OpenText(jsonfile)){using (JsonTextReader reader = new JsonTextReader(file)){jObject = (JObject)JToken.ReadFrom(reader);}}// fetch data from json scripttotal = Convert.ToInt32(jObject["count"].ToString());if(total <= 0){return;}items = jObject["items"];if(items == null){return;}// fetch each datafor (int i = 0; i < total; i ++){int id = Convert.ToInt32(items[i]["ID"].ToString());string name = items[i]["NAME"].ToString();id_array[i] = id;name_array[i] = name;}}private void OK_Click(object sender, RoutedEventArgs e){int id_val;string name_val = name.Text;int i = 0;int j = 0;if (id.Text == ""){MessageBox.Show("ID input should not be empty!");return;}id_val = Convert.ToInt32(id.Text);if(id_val >= 1000){MessageBox.Show("ID should be smaller than 1000!");goto Final;}switch(select_option){case 1: //addif(name_val == ""){MessageBox.Show("Name can not be empty!");goto Final;}if (total == 1000){MessageBox.Show("Array is full!");goto Final;}for (i = 0; i < total; i++){if(id_array[i] == id_val){MessageBox.Show("Find same id!");goto Final;}}id_array[total] = id_val;name_array[total] = name_val;total += 1;MessageBox.Show("Add successfully!");break;case 2://delif (total == 0){MessageBox.Show("Array is empty!");goto Final;}for (i = 0; i < total; i++){if (id_array[i] == id_val){break;}}if(i == total){MessageBox.Show("Failed to find relevant id!");goto Final;}for(j = i+1; j < total; j++){id_array[j - 1] = id_array[j];name_array[j - 1] = name_array[j];}total -= 1;MessageBox.Show("Del successfully!");break;case 3://updateif (name_val == ""){MessageBox.Show("Name can not be empty!");goto Final;}if (total == 0){MessageBox.Show("Array is empty!");goto Final;}for (i = 0; i < total; i++){if (id_array[i] == id_val){break;}}if (i == total){MessageBox.Show("Failed to find relevant id!");goto Final;}name_array[i] = name_val;MessageBox.Show("Update successfully!");break;case 4://searchif (total == 0){MessageBox.Show("Array is empty!");goto Final;}for (i = 0; i < total; i++){if (id_array[i] == id_val){break;}}if (i == total){MessageBox.Show("Failed to find relevant id!");goto Final;}MessageBox.Show("Name is " + name_array[i]);break;default:break;}// display dataupdate_data();Final:id.Text = "";name.Text = "";}private void update_data(){string data_text = "";for(int i = 0; i < total;i++){data_text += Convert.ToString(id_array[i]);data_text += " ";data_text += name_array[i];data_text += "\n";}all_data.Text = "";all_data.Text = data_text;}private void Cancel_Click(object sender, RoutedEventArgs e){this.Close();}private void Save_Click(object sender, RoutedEventArgs e) // important callback function{JArray items = new JArray();JObject header = new JObject();// save to arrayfor(int i = 0; i < total; i++){JObject jobj = new JObject();jobj["ID"] = id_array[i];jobj["NAME"] = name_array[i];items.Add(jobj);}// save to headerheader["count"] = total;header["items"] = items;// save datausing (System.IO.StreamWriter file = new System.IO.StreamWriter("data.json")){file.Write(header.ToString());}MessageBox.Show("Save successfully!");}private void Add_Checked(object sender, RoutedEventArgs e){select_option = 1; //addname.IsEnabled = true;}private void Del_Checked(object sender, RoutedEventArgs e){select_option = 2; //delname.Text = "";name.IsEnabled = false;}private void Update_Checked(object sender, RoutedEventArgs e){select_option = 3; //updatename.IsEnabled = true;}private void Search_Checked(object sender, RoutedEventArgs e){select_option = 4; //searchname.Text = "";name.IsEnabled = false;}}
}

        至于说代码中的入参处理、异常处理、使用习惯处理,这些部分只能靠大家自己去慢慢体会和了解了。有了这份代码做基础,以后的crud代码,也就是增删改查操作都逃不了这个范畴。而且我们的数据是真正保存在json文件中的,不存在丢失的风险,这也让开发的软件进一步拓展了实用性和可靠性。

5、运行测试

        运行测试就比较简单了,直接编译执行就好了,不出意外就可以看到这样的运行画面了,和之前设计稍微有点区别,

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

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

相关文章

HCIP---RSTP/MSTP

文章目录 目录 文章目录 前言 一.RSTP诞生背景 二.RSTP对比STP的快速收敛机制 端口角色变化 接口状态变化 RSTP-BPDU 指定端口- P/A机制 BPDU发送变化 端口状态快速切换 优化拓扑变更机制 三.MSTP MSTP诞生背景 MSTP相关概念 MSTP配置 总结 前言 STP协议虽然能够解决环…

软件测试之压力测试详解

一、什么是压力测试 软件测试中&#xff1a;压力测试&#xff08;Stress Test&#xff09;&#xff0c;也称为强度测试、负载测试。压力测试是模拟实际应用的软硬件环境及用户使用过程的系统负荷&#xff0c;长时间或超大负荷地运行测试软件&#xff0c;来测试被测系统的性能、…

es6从url中获取想要的参数

第一种方法 很古老&#xff0c;通过 split 方法慢慢截取&#xff0c;可行是可行但是这个方法有一个弊端&#xff0c;因为 split 是分割成数组了&#xff0c;只能按照下标的位置获取值&#xff0c;所以就是参数位置一旦发生变化&#xff0c;那么获取到的值也就错位了 let user…

LeetCode刷题--- 验证二叉搜索树

个人主页&#xff1a;元清加油_【C】,【C语言】,【数据结构与算法】-CSDN博客 http://t.csdnimg.cn/ZxuNL个人专栏&#xff1a;力扣递归算法题 http://t.csdnimg.cn/ZxuNL 【C】 http://t.csdnimg.cn/c9twt 前言&#xff1a;这个专栏主要讲述递归递归、搜索与回溯算法&#x…

IDEA中工具条中的debug按钮不能用了显示灰色

IDEA中工具条中的debug按钮不能用了显示灰色 1. 问题描述 IDEA上的DEBUG按钮突然变成了灰色&#xff1a; 2. 解决办法 一通搜索&#xff0c;终于找到解决办法 点击 File -> Project Structure如下图操作 3. 重启&#xff0c;解决 4. 参考 https://www.cnblogs.com…

k8s上安装KubeSphere

&#x1f369;安装KubeSphere &#x1f36a;前置环境&#x1f36a;安装nfs-server文件系统&#x1f36a;配置nfs-client&#x1f36a;配置默认存储&#x1f36a;创建了一个存储类&#x1f36a;metrics-server集群指标监控组件 &#x1f36a;安装KubeSphere&#x1f36a;执行安装…

基于ssm志愿者招募网站源码和论文

网络的广泛应用给生活带来了十分的便利。所以把志愿者招募管理与现在网络相结合&#xff0c;利用java技术建设志愿者招募网站&#xff0c;实现志愿者招募的信息化。对于进一步提高志愿者招募管理发展&#xff0c;丰富志愿者招募管理经验能起到不少的促进作用。 志愿者招募网站…

《三十一》开发模式构建工具 Vite

20的1小时59分 基于 Vite2。 在实际开发中&#xff0c;编写的代码往往是不能被浏览器直接识别的&#xff0c;例如 ES6、React、Vue、TypeScript 等&#xff0c;必须通过构建工具来对代码进行转换、编译&#xff0c;例如 Webpack、Rolluop、Vite 等。 Vite&#xff1a;下一代前…

docker 资源控制

Docker的资源控制 对容器使用宿主机的资源进行限制&#xff0c;如cpu&#xff0c;内存&#xff0c;磁盘I/O Docker使用linux自带的功能cgroup(control grouos)是linux内核系统提供的一种可以限制&#xff0c;记录&#xff0c;隔离进程组使用的物理资源 Docker借助这个机制&…

Python 小程序之动态进度条

动态进度条 文章目录 动态进度条前言一、显示效果二、基本思路1.引入库2.基本参数3.数据处理 三、数据处理1.计算完成百分比2.动态显示进度条3.打印完成时间 总结 前言 大家在下载东西的时候都会看到有一个动态的进度条在那里。进度条走完了也就下载完了。下面我写一个简易版的…

【音视频 | H.264】H.264编码详解

&#x1f601;博客主页&#x1f601;&#xff1a;&#x1f680;https://blog.csdn.net/wkd_007&#x1f680; &#x1f911;博客内容&#x1f911;&#xff1a;&#x1f36d;嵌入式开发、Linux、C语言、C、数据结构、音视频&#x1f36d; &#x1f923;本文内容&#x1f923;&a…

浅谈web性能测试

什么是性能测试&#xff1f; web性能应该注意些什么&#xff1f; 性能测试&#xff0c;简而言之就是模仿用户对一个系统进行大批量的操作&#xff0c;得出系统各项性能指标和性能瓶颈&#xff0c;并从中发现存在的问题&#xff0c;通过多方协助调优的过程。而web端的性能测试…

大数据机器学习与深度学习——回归模型评估

大数据机器学习与深度学习——回归模型评估 回归模型的性能的评价指标主要有&#xff1a;MAE(平均绝对误差)、MSE(平均平方误差)、RMSE(平方根误差)、R2_score。但是当量纲不同时&#xff0c;RMSE、MAE、MSE难以衡量模型效果好坏&#xff0c;这就需要用到R2_score。 平均绝对…

专业证件翻译哪里比较正规?

随着国际化的步伐不断加快&#xff0c;我们与国外的交流日益频繁&#xff0c;无论是出国留学、旅游还是商务活动&#xff0c;都离不开证件翻译。那么&#xff0c;在选择证件翻译服务时&#xff0c;我们应该注意哪些事项呢&#xff1f;哪里能找到正规的翻译服务呢&#xff1f; 我…

Python之Requests库使用总结

概述 Requests是python中一个很Pythonic的HTTP库&#xff0c;用于构建HTTP请求与解析响应 Requests开发哲学 Beautiful is better than ugly.(美丽优于丑陋) Explicit is better than implicit.(直白优于含蓄) Simple is better than complex.(简单优于复杂) Complex is bett…

winform使用CefSharp嵌入VUE网页并交互

1、NuGet添加CefSharp 如果下载慢或失败可以更新下载源 腾讯资源https://mirrors.cloud.tencent.com/nuget/华为资源https://repo.huaweicloud.com/repository/nuget/v3/index.json 2、将项目平台改为X64 3、在winform窗体添加cef using CefSharp; using CefSharp.WinForms; u…

【ret2hbp】一道板子测试题 和 SCTF2023 - sycrpg

前言 ret2hbp 主要是利用在内核版本 v6.2.0 之前&#xff0c;cpu_entry_area mapping 区域没有参与随机化的利用。其主要针对的场景如下&#xff1a; 1&#xff09;存在任意地址读&#xff0c;泄漏内核地址 2&#xff09;存在无数次任意地址写&#xff0c;泄漏内核地址并提权…

设计模式——观察者模式(Observer Pattern)

概述 观察者模式是使用频率最高的设计模式之一&#xff0c;它用于建立一种对象与对象之间的依赖关系&#xff0c;一个对象发生改变时将自动通知其他对象&#xff0c;其他对象将相应作出反应。在观察者模式中&#xff0c;发生改变的对象称为观察目标&#xff0c;而被通知的对象称…

phpstudy搭建WordPress教程

一、phpstudy新建配置WordPress 打开phpstudy&#xff0c;启动Apache&#xff08;或者Nginx&#xff09;和MySQL服务 来到数据库部分&#xff0c;点击[创建数据库]&#xff0c;填写新建数据库的名称&#xff0c;用户名以及密码&#xff0c;完成后点击确认 来到网站部分&#x…

C++STL的stack和queue(超详解)

文章目录 前言stack栈的题目最小栈JZ31 栈的压入、弹出序列 stack的模拟实现queue的模拟实现 前言 栈和队列这一块其实有数据结构的基础&#xff0c;学起来非常简单。 stack 栈的成员函数就这么写&#xff0c;除了emplace其他都已经非常熟悉了。 stack没有迭代器吗&#xff…