C#使用XML和Treeview结合实现复杂数据采集功能

  一个项目的数据表暂时没有定下来,但是有了一些确定性:
  1、比较复杂,可能变化;
  2、大部分是选择项目,因为输入项目都差不多;
  3、应用程序是C/S的窗体应用。
  对于这样的用户需求,为了快速让用户看到功能效果,可以使用XML结合Treeview来实现。
  最终的输入效果图:

   对于上图的实现,需要完成的工作:

  1、定义XML文件

<事故调查 value="" max="100">
	<气候因素 Value="" Formula="Item*1.5">
		<气温 type="Textbox" max="" min="" value="" />
		<湿度 type="Textbox" max="" min="" value="" />
	</气候因素>
	<地质灾害 Value="" Formula="Item" type="Radio">
		<option caption="泥石流" value="5" />
		<option caption="水灾" value="10" />
		<option caption="地震" value="20" />
	</地质灾害>
	<人为因素 Value="" Formula="Item" type="Checkbox">
		<input caption="管理失职" value="20" />
		<input caption="能力欠缺" value="20" />
		<input caption="制度不健全" value="15" />
	</人为因素>
</事故调查>

  2、将XML文件存入数据采集模板并存入数据库,需要数据录入的时候读出来即可。
  ⑴新增模板

string InsertQuery = $"INSERT INTO InputThemeXml(F01,F02,F03) VALUES (@ThemeName,@XmlData,@ThemeMemo)";
SqlCommand MyCommand = new SqlCommand(InsertQuery, DBConn);
MyCommand.Parameters.AddWithValue("@ThemeName", ThemeName);
MyCommand.Parameters.AddWithValue("@XmlData", XmlData);
MyCommand.Parameters.AddWithValue("@ThemeMemo", ThemeMemo);
int RowAffected = MyCommand.ExecuteNonQuery();
if (RowAffected > 0) { MessageBox.Show("新增-保存成功"); }

  ⑵修改模板

string UpdateSql = $"UPDATE InputThemeXml SET F02=@XmlData,F03=@ThemeMemo WHERE F01=@ThemeName";
SqlCommand MyCommand1 = new SqlCommand(UpdateSql, DBConn);
MyCommand1.Parameters.AddWithValue("@ThemeName", ThemeName);
MyCommand1.Parameters.AddWithValue("@XmlData", XmlData);
MyCommand1.Parameters.AddWithValue("@ThemeMemo", ThemeMemo);
int RowAffected1 = MyCommand1.ExecuteNonQuery();
if (RowAffected1 > 0) { MessageBox.Show("修改-保存成功"); }

  3、准备工作
  ⑴准备图片,为16x16的PNG文件,创建资源文件并放入Textbox、Radio、RadioChecked(选择时显示)、Checkbox、CheckboxChecked(选中时显示);
  ⑵在窗体初始化时定义资源

//定义资源
MyImageList.Images.Add("Default", YQCYPRAS.Resourse.Resource1.line  as Image);
MyImageList.Images.Add("Radio",YQCYPRAS.Resourse.Resource1.radio as Image);
MyImageList.Images.Add("RadioChecked", YQCYPRAS.Resourse.Resource1.radioChecked as Image);
MyImageList.Images.Add("Checkbox", YQCYPRAS.Resourse.Resource1.checkbox as Image);
MyImageList.Images.Add("CheckboxChecked", YQCYPRAS.Resourse.Resource1.checkboxChecked as Image);
MyImageList.Images.Add("Textbox", YQCYPRAS.Resourse.Resource1.textbox as Image);
treeView1.ImageList = MyImageList;

  ⑶事件挂载

treeView1.MouseDown+= treeView1_MouseDown;
treeView1.KeyDown += treeView1_KeyDown;
treeView1.LostFocus += treeView1_LostFocus;
treeView1.NodeMouseDoubleClick+= treeView1_MouseDouleClick;

  4、读取XML模板并操作Treeview的生成
  ⑴ 读取XML模板

//创建一个Xml文档对象
XmlDocument XmlDoc = new XmlDocument();
//加载XML数据
string SelectThemeName = comboBox2.SelectedItem.ToString();
DBConn.Open();
string SqlQuery = $"SELECT F02 FROM InputThemeXml WHERE F01='{SelectThemeName}'";
SqlCommand MyCommand = new SqlCommand(SqlQuery, DBConn);
SqlDataReader MyReader = MyCommand.ExecuteReader();
if (MyReader.Read()) { XmlDoc.LoadXml(MyReader["F02"].ToString()); }
MyReader.Close();
DBConn.Close();
//获取文档的根节点
XmlNode RootNode = XmlDoc.SelectSingleNode(SelectThemeName);
//将根节点添加到treeview1控件中
TreeNode RootTreeviewNode = new TreeNode(SelectThemeName);
treeView1.Nodes.Add(RootTreeviewNode);
//递归生成Treeview
AddNodesToTreeview(RootNode, RootTreeviewNode);
treeView1.ExpandAll();
MessageBox.Show("OK");

  ⑵关键在于递归生成Treeview,是AddNodesToTreeview(RootNode, RootTreeviewNode);

        public void AddNodesToTreeview(XmlNode MyXmlNode,TreeNode MyTreeNode)
        {
            //遍历该节点下的所有的子节点
            foreach(XmlNode MyNode in MyXmlNode.ChildNodes)
            {
                string StrXmlNodeType = "";
                if (HasAttribute(MyNode, "type"))
                {
                    StrXmlNodeType=GetAttrValue(MyNode, "type");                    
                }
                //textBox4.Text += StrXmlNodeType + Environment.NewLine;
                //判断节点是否为Textbox(编辑框)、Radio(单选按钮)、Checkbox(复选框)
                if (StrXmlNodeType == "")
                {
                    //将子节点添加到treeview控件中
                    TreeNode ChildTreeNode = new TreeNode(MyNode.Name);
                    ChildTreeNode.ImageKey= "Default";
                    MyTreeNode.Nodes.Add(ChildTreeNode);
                    //如果该子节点下面还有子节点,就递归调用继续生成
                    if (MyNode.HasChildNodes)
                    {
                        AddNodesToTreeview(MyNode, ChildTreeNode);
                    }
                }
                else
                {
                    switch(StrXmlNodeType) {
                        case "Textbox":
                            TreeNode TextboxNode = new TreeNode(MyNode.Name);
                            TextboxNode.Tag= "Textbox";
                            TextboxNode.ImageKey= "Textbox";
                            TextboxNode.SelectedImageKey= "Textbox";
                            MyTreeNode.Nodes.Add(TextboxNode);
                            break;
                        case "Radio":
                            //单选按钮,表明子节点全部是Radio按钮
                            TreeNode ParentRadioNode=new TreeNode(MyNode.Name);
                            MyTreeNode.Nodes.Add(ParentRadioNode);
                            //添加子节点
                            SetChildNodeRadio(MyNode, ParentRadioNode);
                            break;
                        case "Checkbox":
                            //复选框
                            TreeNode ParentCheckboxNode = new TreeNode(MyNode.Name);
                            MyTreeNode.Nodes.Add(ParentCheckboxNode);
                            SetChildNodeCheckbox(MyNode, ParentCheckboxNode);
                            break;
                    }
                }
            }
        }

        public void SetChildNodeRadio(XmlNode ParentXmlNode, TreeNode ParentNode)
        {
            //遍历所有的子节点进行设置
            foreach(XmlNode ChildXmlNode in ParentXmlNode.ChildNodes)
            {
                string STemp = "";
                STemp = GetAttrValue(ChildXmlNode,"caption");
                TreeNode ChildRadioNode = new TreeNode(STemp);
                ChildRadioNode.Tag= "Radio";
                ChildRadioNode.ImageKey = "Radio";
                ParentNode.Nodes.Add(ChildRadioNode);
            }
        }

  5、编写事件处理

        private void treeView1_MouseDown(object sender, MouseEventArgs e)
        {
            // 获取鼠标点击的位置
            TreeNode FocusNode = treeView1.GetNodeAt(e.Location);
            if (FocusNode != null)
            {
                // 获取鼠标点击的位置是否在节点的图标上
                TreeViewHitTestInfo hitTestInfo = treeView1.HitTest(e.Location);
                if (hitTestInfo.Location == TreeViewHitTestLocations.Image)
                {
                    // 鼠标点击了节点的图标
                    switch (FocusNode.Tag.ToString())
                    {
                        case "Radio":
                            // 取消同级节点的选中状态
                            foreach (TreeNode node1 in FocusNode.Parent.Nodes)
                            {
                                if (node1 != FocusNode)
                                {
                                    node1.ImageKey = "Radio";
                                    node1.SelectedImageKey = "Radio";
                                }
                            }
                            // 设置当前节点为选中状态
                            FocusNode.ImageKey = "RadioChecked";
                            FocusNode.SelectedImageKey = "RadioChecked";
                            break;
                        case "Checkbox":
                            if (FocusNode.ImageKey == "Checkbox")
                            {
                                FocusNode.ImageKey = "CheckboxChecked";
                                FocusNode.SelectedImageKey = "CheckboxChecked";
                            }
                            else
                            {
                                FocusNode.ImageKey = "Checkbox";
                                FocusNode.SelectedImageKey = "Checkbox";
                            }
                            break;
                        case "Textbox":
                            //System.Windows.Forms.TextBox MyTextbox=new System.Windows.Forms.TextBox();
                            //MyTextbox.Text = "请输入值:";
                            //MyTextbox.Location= new System.Drawing.Point(FocusNode.Bounds.Left+120, FocusNode.Bounds.Top -1);
                            //MyTextbox.Width= 120;
                            //MyTextbox.BorderStyle = BorderStyle.FixedSingle;
                            break;
                    }
                    treeView1.Invalidate();
                }

                if (hitTestInfo.Location == TreeViewHitTestLocations.Label)
                {
                    //点击标签
                    if ( FocusNode.Tag !=null)
                    {
                        switch (FocusNode.Tag.ToString())
                        {
                            case "Radio":
                                if (FocusNode.ImageKey == "RadioChecked")
                                {
                                    FocusNode.SelectedImageKey = "RadioChecked";
                                }
                                if (FocusNode.ImageKey == "Radio")
                                {
                                    FocusNode.SelectedImageKey = "Radio";
                                }
                                break;
                            case "Checkbox":
                                if (FocusNode.ImageKey == "Checkbox")
                                {
                                    FocusNode.SelectedImageKey = "Checkbox";
                                }
                                if (FocusNode.ImageKey == "CheckboxChecked")
                                {
                                    FocusNode.SelectedImageKey = "CheckboxChecked";
                                }
                                break;
                            case "Textbox":
                                FocusNode.BeginEdit();
                                break;
                            default: break;
                        }
                        treeView1.Invalidate();
                    }
                    
                }
            }
            }

  6、对XML的属性的判断和值获取

        public Boolean HasAttribute(XmlNode MyXmlNode,string StrAttr)
        {
            //判断是否具有属性
            Boolean ReturnBool=false;
            if (MyXmlNode.Attributes != null && MyXmlNode.Attributes[StrAttr] != null)
            {
                ReturnBool=true;
            }
            return ReturnBool;
        }

        public string GetAttrValue(XmlNode MyXmlNode,string StrAttr)
        {
            //得到属性值
            string ReturnStr = "";
            if (MyXmlNode.Attributes != null && MyXmlNode.Attributes[StrAttr] != null)
            {
                    ReturnStr= MyXmlNode.Attributes[StrAttr].Value;
            }
            return ReturnStr;
        }

  对于XML生成Treeview有几种方法,最麻烦的方法是继承Treeview后重写,这能实现想要的所有功能,稍微麻烦一些的是获取节点位置后根据用户的需求动态生成输入组件放置到相应的位置,我采用的是最简单的方法,更改节点的图片文件来满足用户的需求。

  需要注意的问题:
  ⑴、节点的imageKey和SelectimageKey分别是节点正常显示的图片和节点被选中时的图片;
  ⑵、节点点击图片和点击文本标签要分别处理;
  ⑶、对于Radio的处理是同级只能显示一个被选中,对于Checkbox是可以多选的;
  ⑷、XML文档与Treeview的数据是同步的。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

搭建个人hMailServer 邮件服务实现远程发送邮件

文章目录 1. 安装hMailServer2. 设置hMailServer3. 客户端安装添加账号4. 测试发送邮件5. 安装cpolar6. 创建公网地址7. 测试远程发送邮件8. 固定连接公网地址9. 测试固定远程地址发送邮件 转载自cpolar极点云文章&#xff1a;搭建个人hMailServer 邮件服务实现远程发送邮件 hM…

如何在编程中中实现负载均衡和容错处理

什么是容错 容错是指系统&#xff08;计算机、网络、云集群等&#xff09;在其一个或多个组件发生故障时继续运行而不会中断的能力。 创建容错系统的目的是防止由单点故障引起的中断&#xff0c;确保任务关键型应用程序或系统的高可用性和业务连续性。 容错系统使用备份组件…

【Twitter爬虫】Twitter网络爬虫

利用selenium爬取Twitter 从2月9日起&#xff0c;Twitter不再支持免费访问Twitter API&#xff0c;继续使用Twitter API支付较高的费用。下面将介绍一种绕过Twitter API爬取推文的方式 Selenium Webdriver框架 首先介绍一下Selenium Webdriver&#xff0c;这是一款web自动化…

计算机专业大学如何自学?常用网站和工具

耗时5小时&#xff0c;第一个B站视频&#xff0c;满足分享欲 计算机专业现状 or 困境&#xff1f;如何自学&#xff1f;常用网站科普&#xff01;_哔哩哔哩_bilibili &#x1f446;发了个视频&#xff0c;结合文章中的链接&#xff0c;保存到自己浏览器收藏夹里就完了 目录 …

React修改Antd组件的样式

修改默认的antd组件&#xff0c;需要使用global import React, { useState, useEffect } from react; import { Tabs, Rate, Steps } from antd; import styles from ./index.less;const Index (props) >{return (<div className{styles.class_steps}><Stepsprog…

maven 环境配置踩坑

今晚在跟着视频学习spring的时候&#xff0c;创建maven工程&#xff0c;一直提示Sync 下载异常。搞了一晚上终于搞定了环境。下面给出一下今晚的总结。 1、确保maven安装并配置好环境变量。 下载并安装maven后&#xff0c;还需要在电脑上配置maven的环境变量。这部分参考网络教…

Hyperledger Fabric网络快速启动

目录 1、网络服务配置 2、关联的docker-compose-base.yaml 各Peer节点容器设置如下信息。 3、被关联的Peer-base.yaml 4、启动网络 2、完成通道的创建 2.1将节点加入应用通道 更新锚节点 2.为什么要创建节点并将其加入应用通道中&#xff1f; 1、网络服务配置 由于要启动…

『赠书活动 | 第十三期』《算力经济:从超级计算到云计算》

&#x1f497;wei_shuo的个人主页 &#x1f4ab;wei_shuo的学习社区 &#x1f310;Hello World &#xff01; 『赠书活动 &#xff5c; 第十三期』 本期书籍&#xff1a;《算力经济&#xff1a;从超级计算到云计算》 赠书规则&#xff1a;评论区&#xff1a;点赞&#xff5c;收…

SFP6012-ASEMI代理MHCHXM(海矽美)二极管SFP6012

编辑&#xff1a;ll SFP6012-ASEMI代理MHCHXM&#xff08;海矽美&#xff09;二极管SFP6012 型号&#xff1a;SFP6012 品牌&#xff1a;MHCHXM&#xff08;海矽美&#xff09; 封装&#xff1a;TO-247AB 恢复时间&#xff1a;≤75ns 正向电流&#xff1a;30A 反向耐压&a…

基于Python的电影票房爬取与可视化系统的设计与实现

博主介绍&#xff1a;✌全网粉丝30W,csdn特邀作者、博客专家、CSDN新星计划导师、java领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ &#x1f345;文末获取源码联系&#x1f345; &#x1f447;&#x1f3fb; 精彩专…

FlutterUnit 已上架 iOS,暗色模式全面支持

theme: cyanosis 一、FlutterUnit 的全平台支持 FlutterUnit 是我的一个开源项目&#xff0c;基于 Flutter 构建的一个 全平台 应用程序。现在很荣幸地宣布: FlutterUnit 已经上架 iOS 的 App Store &#xff0c;自此主流的几大平台均已提供体验。 项目地址: https://github.co…

Java中常见的线程池以及ThreadPoolTaskExecutor和ThreadPoolExecutor

线程池的基本组成&#xff1a; 线程管理器&#xff1a;用于创建并管理线程池&#xff0c;负责线程池的创建、销毁以及任务的添加。 工作线程&#xff1a;线程池中的线程&#xff0c;负责执行任务&#xff0c;没有任务时处于等待状态。 任务接口&#xff1a;每个任务必须实现的…

B051-cms06-退出 回车登录 登录拦截 记住我 SVN

目录 注销功能实现1.找到退出按钮修改请求路径2.后端删除Session并跳转到登录页面 回车登录功能登陆拦截1.编写登录拦截器2.配置拦截器 记住我后端实现页面实现 取消记住我后端实现页面实现 注销功能实现 1.找到退出按钮修改请求路径 header.jsp <% page language"j…

Linux上安装matlab

首先需要下载文件&#xff0c;微人大正版软件下载里有 然后直接点击&#xff0c;就可以就可以安装&#xff0c;不需要使用挂载命令&#xff0c;然后使用 ./install就可以进行安装了&#xff0c;这里记住是得登录自己的人大邮箱&#xff0c;否则无法激活&#xff0c;然后修改安…

LeetCode·每日一题·2490. 回环句·模拟

作者&#xff1a;小迅 链接&#xff1a;https://leetcode.cn/problems/circular-sentence/solutions/2325227/mo-ni-zhu-shi-chao-ji-xiang-xi-by-xun-ge-x65e/ 来源&#xff1a;力扣&#xff08;LeetCode&#xff09; 著作权归作者所有。商业转载请联系作者获得授权&#xff0…

MySQL 主从复制与读写分离

概念 主从复制与读写分离的意义 企业中的业务通常数据量都比较大&#xff0c;而单台数据库在数据存储、安全性和高并发方面都无法满足实际的需求&#xff0c;所以需要配置多台主从数据服务器&#xff0c;以实现主从复制&#xff0c;增加数据可靠性&#xff0c;读写分离&#x…

不是吧,交换机坏了你还只会这么排查?

又见面了&#xff0c;我的网工朋友 上次给你分享了交换机和路由器的对接上网配置案例&#xff0c;还记得吗&#xff1f; 今天这篇&#xff0c;和你聊聊交换机接口故障。 接口故障这件事&#xff0c;对咱们网工来说其实算是家常便饭了。 工作到现在&#xff0c;你复盘一下&a…

实战:求年月日时间前后遇到的坑和解决方式

这里写目录标题 前言正确实例&#xff1a;错误实例&#xff1a; 需求 前言 这周接到一个时间转换任务需要处理&#xff0c;本来没什么问题&#xff0c;后来完成后发现时间有偏差&#xff0c;又重写了一遍代码&#xff0c;感觉很有记录必要性&#xff0c;希望看过的小伙伴可以避…

计算机网络——数据链路层

序言 问&#xff1a;数据链路层在现在的社会起到什么作用&#xff1f; 答&#xff1a;数据链路层在现在的社会起到关键性作用&#xff0c;比如&#xff1a;数据传输和通信&#xff1b;网络连接和互联互通&#xff1b;错误检测和纠正&#xff1b;媒体访问控制&#xff1b;网络性…

启动一个qemu虚拟机

安装qemu&#xff1a; 编译内核&#xff1a; 编译rootfs&#xff1b; 启动&#xff1a; qemu-system-x86_64 -kernel ./linux-4.14.320/arch/x86_64/boot/bzImage -hda ./busybox-1.36.1/rootfs.img -append "root/dev/sda consolettyS0" -nographic 效果图&am…