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

news2024/9/25 21:28:23

  一个项目的数据表暂时没有定下来,但是有了一些确定性:
  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的数据是同步的。

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

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

相关文章

C++ 基础知识 面试题(一)

1.变量的声明与定义 声明&#xff1a;int x; //告诉编译器这个变量的类型和名称 定义&#xff1a;int x 0; //告诉编译器这个变量的类型和名称&#xff0c;为该变量分配内存空间&#xff0c;并初始化该变量 主要区别在于是否为变量分配内存空间 2.extern关键字 用法一&…

Apache IoTDB 论文入选数据库领域顶级学术会议 ACM SIGMOD

6 月 18-23 日&#xff0c;ACM SIGMOD 会议在美国西雅图举办。Apache IoTDB 的研究成果论文《Apache IoTDB: A Time Series Database for IoT Applications》在大会做了报告&#xff0c;并进行了 Poster 展示。 01 关于 SIGMOD SIGMOD 数据管理国际会议&#xff08;Special Int…

嵌入式系统BSP开发(二)

快递拿到R16的开发板后&#xff0c;通过官方拿到SOCHIP的相关资料&#xff0c;压缩包的名称是lichee.tar.gz 一&#xff0c;解压相关的资料 tar xzvf r16_lichee.tar.gz 解压后得到的资料如下&#xff1a; yveyve:/data/home/yve/Linux/lichee$ ls brandy buildroot build…

计算物理专题:傅里叶变换与快速傅里叶变换

计算物理专题&#xff1a;傅里叶变换与快速傅里叶变换 傅里叶变换提供一个全新的角度去观察和描述问题&#xff0c;如在量子力学中&#xff0c;动量与坐标表象之间的变换就是傅里叶变换。傅里叶变换同意可以用在数据处理等领域。1965年&#xff0c;Cooley 和 Tukey 提出了快速傅…

redis之主从复制、哨兵、集群

文章目录 一、redis的高可用1.1 redis高可用的概念1.2 Redis的高可用技术 二、redis 主从复制2.1主从复制的原理2.2搭建Redis 主从复制 三、Redis 哨兵模式3.1搭建Redis 哨兵模式3.2启动哨兵模式3.3查看哨兵信息3.4故障模拟 四、Redis 群集模式4.1搭建Redis 群集模式 一、redis…

数据结构--串的定义和基本操作

数据结构–串的定义和基本操作 注:数据结构三要素――逻辑结构、数据的运算、存储结构&#xff08;物理结构) 存储结构不同&#xff0c;运算的实现方式不同 \color{pink}存储结构不同&#xff0c;运算的实现方式不同 存储结构不同&#xff0c;运算的实现方式不同 串的定义 串 …

用Java制作简单的记事本

目录 前言 主界面设计 功能实现 打开 另存为 保存 查找 替换 成员变量 其他方法 警告弹窗 不移动光标更新文本框内容 源代码 总结 转载请注明出处&#xff0c;尊重作者劳动成果。 前言 考完试想写敲一下代码就写了一下这个程序&#xff0c;整个也是写了怎么久…

JavaEE语法第二章之多线程(初级一)

一、认识线程 1.1线程的概念 一个线程就是一个 "执行流"。每个线程之间都可以按照顺序执行自己的代码. 多个线程之间 "同时"执行着多份代码。 一家公司要去银行办理业务&#xff0c;既要进行财务转账&#xff0c;又要进行福利发放&#xff0c;还得进行缴…

Docker常见问题集合

一、Docker安装 1、yum 安装 1&#xff09;更新yum包到最新 yum update2&#xff09;安装软件需要的软件&#xff0c;yum-util&#xff08;提供 yum-config-manager 功能&#xff09;&#xff0c;device-mapper-persistent-data、lvm2&#xff08;devicemapper 驱动依赖&…

mmdetection踩坑记录

1.mmcv-full和mmdetection的版本匹配问题 Readme里应该会给可复现的版本&#xff0c;一定要按照readme里的&#xff0c;这里是一些版本对应关系&#xff0c;像我的mmdet是2.3.0&#xff0c;我就只能装1.0.5的mmcv-full 表格来源&#xff1a;https://blog.csdn.net/qq_55957975/…

高频-测试岗面试题,软件测试面试常问面试题(付答案)

目录&#xff1a;导读 前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结&#xff08;尾部小惊喜&#xff09; 前言 测试流程&#xf…

【Zynq】Xilinx SDK设置编码方式

举例&#xff1a;将Xilinx SDK设置为UTF-8编码 工具栏->Window->Preferences

基于Tensorflow和Keras实现卷积神经网络CNN并进行猫狗识别

文章目录 一、环境配置1、安装Anaconda2、配置TensorFlow、Keras 二、猫狗数据集分类建模3.1 猫狗图像预处理3.2 猫狗分类的实例——基准模型3.1 构建神经网络3.2 配置优化器3.3 图片格式转化3.4 训练模型3.5 保存模型3.6 可视化 三、数据增强四、dropout 层五、参考资料 一、环…

Openresty原理概念篇(十五)Lua 规则和 NGINX 配置文件产生冲突怎么办?

一 Lua 规则和 NGINX 配置文件产生冲突怎么办? ① OpenResty 的名字和语言 说明&#xff1a; 了解openresty的发展史 ② 配置文件的规则优先级 1) 如何各司其职2) 都能满足功能,该如何取舍 理解&#xff1a; 1) rewrite ... break 到POST_WRITE阶段2) 而rewrite_by_lua*…

JAVA的DIFF算法

首先看一下我的文件结构 1.EnumType 类 public enum EnumType {ADD("ADD"),MODIFIED("MODIFIED"), DELETED("DELETED");//创建私有变量private String type;EnumType(String type) {this.type type;} }2.OperationType类 public class Operati…

vue封装svg组件来修改svg图片颜色

文章目录 1、引入依赖2、根目录的vue.config.js配置3、在组件文件夹(compontents)中创建svgIcon.vue4、在src目录下创建icons文件5、处理svg格式的图片6、在main.js文件中引入icons文件中的index.js文件7、使用8、效果图1、项目成功运行后的样子2、直接在html上添加样式&#x…

DEBUG系列三:使用 F9 和 watch point

首先是我随便找了个报错。 报销消息号信息&#xff1a; No pricing procedure could be determined Message No. V1212 1&#xff09;首先可以直接SE91 来追溯这个消息号哪儿报出来的 可以看到下面两个地方可能会报这个消息&#xff0c;可以直接在这两个地方打断点&#xff0c;…

开发一个RISC-V上的操作系统(一)—— 环境搭建

在前面我们使用Verilog实现了一个简易的RISC-V处理器&#xff0c;并且能烧录到板子上跑一些简单C程序&#xff0c;传送门&#xff1a; RISC-V处理器的设计与实现&#xff08;一&#xff09;—— 基本指令集_risc_v处理器_Patarw_Li的博客-CSDN博客 RISC-V处理器的设计与实现&…

电子器件系列41:扁平高压电阻

这种电阻和其他的高压电阻不同&#xff0c;不是绕线电阻而是陶瓷电阻 找到一个大神&#xff0c;他的专栏也得很详细了&#xff0c;贴在这里 https://blog.csdn.net/wkezheng/category_12059870.html 阻容感基础03&#xff1a;电阻器分类&#xff08;1&#xff09;-片式电阻器…