C#TreeView中AfterSelect和BeforeSelect事件自动保存上一次的数据源

83 篇文章 3 订阅
13 篇文章 6 订阅
该示例展示了一个Windows窗体应用,通过TreeView控件实现节点切换时自动保存和更新配置信息。利用Newtonsoft.Json库处理JSON配置文件,保存和加载接口配置数据,包括接口名称、URL、超时时间等参数。程序使用AfterSelect和BeforeSelect事件来确保节点切换时数据的持久化。
摘要由CSDN通过智能技术生成

当切换TreeView的某一个节点时,自动保存上一次节点的数据源

思路:

1.定义一个节点成员变量:记录上一次被选中的节点,当上一个节点与本节点不一致时,保存上一个节点的内容到 缓存对象中

TreeNode LastSelectedNode = null;

2.TreeView的AfterSelect事件加载当前配置,并记录选中的节点
 LastSelectedNode = e.Node;

3.TreeView的BeforeSelect事件如果上一次节点 与本次的节点不一致,就先保存上一次节点的内容到内存中UpdateInterfaceInfo(LastSelectedNode.Text);

新建窗体应用程序AutoSaveTreeNodeDataDemo,将默认的Form1修改为FormSaveTreeNodeExchange,窗体设计如图:

添加对 Newtonsoft.Json.dll类库的引用。新建config.json文件,复制到输出目录:始终复制

配置文件config.json内容如下:

{
  "AllConfig": [
    {
      "Name": "工位A进站校验接口",
      "Enabled": true,
      "Url": "http://abc.com/XXService?wsdl",
      "ReceiveTimeout": 30000,
      "UserName": "admin",
      "Password": "12345",
      "ListExtensionParam": [
        {
          "Key": "Operation",
          "Val": "AAA",
          "Des": "操作工站"
        },
        {
          "Key": "Resource",
          "Val": "RRR",
          "Des": "资源"
        },
        {
          "Key": "Item",
          "Val": "ITEM",
          "Des": ""
        },
        {
          "Key": "ProcessMode",
          "Val": "Start",
          "Des": "处理方式"
        }
      ],
      "ListMesData": []
    },
    {
      "Name": "工位A数据上传接口",
      "Enabled": true,
      "Url": "http://abc.com/YYService?wsdl",
      "ReceiveTimeout": 30000,
      "UserName": "AA",
      "Password": "12345",
      "ListExtensionParam": [
        {
          "Key": "Operation",
          "Val": "AAA",
          "Des": "操作工站"
        },
        {
          "Key": "Resource",
          "Val": "MMAW0012",
          "Des": "资源"
        },
        {
          "Key": "ProcessMode",
          "Val": "COMPLETE_AND_POST",
          "Des": "处理方式"
        }
      ],
      "ListMesData": [
        {
          "LocalName": "SubBarcode",
          "LocalDescription": "子条码",
          "MesName": "ZTM",
          "DataType": "STRING",
          "Unit": "",
          "Value": "Sub"
        },
        {
          "LocalName": "WorkStation",
          "LocalDescription": "工位",
          "MesName": "GWH",
          "DataType": "NUMBER",
          "Unit": "",
          "Value": 1
        },
        {
          "LocalName": "WeldSpeed",
          "LocalDescription": "焊接速度",
          "MesName": "HJSD",
          "DataType": "NUMBER",
          "Unit": "mm/s",
          "Value": 200
        },
        {
          "LocalName": "GasFlow",
          "LocalDescription": "保护气流量",
          "MesName": "BHQLL",
          "DataType": "NUMBER",
          "Unit": "",
          "Value": 7.2E-3
        },
        {
          "LocalName": "WeldVoltage",
          "LocalDescription": "电压",
          "MesName": "DY",
          "DataType": "NUMBER",
          "Unit": "伏特",
          "Value": 5.67
        },
        {
          "LocalName": "WeldPower",
          "LocalDescription": "输出功率",
          "MesName": "SCGL",
          "DataType": "NUMBER",
          "Unit": "W",
          "Value": 1234.56
        }
      ]
    },
    {
      "Name": "工位B进站校验接口",
      "Enabled": true,
      "Url": "http://abc.com/ZZService?wsdl",
      "ReceiveTimeout": 30000,
      "UserName": "BB",
      "Password": "12345",
      "ListExtensionParam": [
        {
          "Key": "Operation",
          "Val": "BBB",
          "Des": "操作工站"
        },
        {
          "Key": "Resource",
          "Val": "XXX",
          "Des": "资源号"
        },
        {
          "Key": "FindInventory",
          "Val": "True",
          "Des": "是否查找库存"
        },
        {
          "Key": "ProcessMode",
          "Val": "CheckStatus",
          "Des": "处理方式"
        }
      ],
      "ListMesData": []
    },
    {
      "Name": "工位B数据上传接口",
      "Enabled": true,
      "Url": "http://abc.com/BBService?wsdl",
      "ReceiveTimeout": 30000,
      "UserName": "BB",
      "Password": "12345",
      "ListExtensionParam": [
        {
          "Key": "Operation",
          "Val": "BBB",
          "Des": "操作工站"
        },
        {
          "Key": "Resource",
          "Val": "YTR",
          "Des": ""
        },
        {
          "Key": "ProcessMode",
          "Val": "COMPLETE_AND_POST",
          "Des": "处理方式"
        }
      ],
      "ListMesData": [
        {
          "LocalName": "DataItem1",
          "LocalDescription": "数据项1",
          "MesName": "SJX1",
          "DataType": "STRING",
          "Unit": "",
          "Value": "Sub"
        },
        {
          "LocalName": "DataItem2",
          "LocalDescription": "数据项2",
          "MesName": "SJX2",
          "DataType": "NUMBER",
          "Unit": "毫米",
          "Value": 1
        },
        {
          "LocalName": "DataItem3",
          "LocalDescription": "数据项3",
          "MesName": "SJX3",
          "DataType": "NUMBER",
          "Unit": "秒",
          "Value": 200
        },
        {
          "LocalName": "DataItem4",
          "LocalDescription": "数据项4",
          "MesName": "SJX4",
          "DataType": "NUMBER",
          "Unit": "",
          "Value": 7.2E-3
        },
        {
          "LocalName": "DataItem5",
          "LocalDescription": "数据项5",
          "MesName": "SJX5",
          "DataType": "NUMBER",
          "Unit": "",
          "Value": 5.67
        },
        {
          "LocalName": "DataItem6",
          "LocalDescription": "数据项6",
          "MesName": "SJX6",
          "DataType": "NUMBER",
          "Unit": "",
          "Value": 1234.56
        }
      ]
    }
  ]
}

新建与config.json相对应的实体类文件MesInterfaceConfig.cs。

MesInterfaceConfig.cs源程序如下:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace AutoSaveTreeNodeDataDemo
{
    /// <summary>
    /// 所有接口配置
    /// </summary>
    public class MesInterfaceConfig
    {
        public MesInterfaceConfig()
        {
            AllConfig = new List<InterfaceConfig>();
        }
        /// <summary>
        /// 所有接口配置列表
        /// </summary>
        public List<InterfaceConfig> AllConfig { get; set; }
    }

    /// <summary>
    /// 接口基本参数,扩展参数,上传数据参数
    /// </summary>
    public class InterfaceConfig
    {
        public InterfaceConfig()
        {
            ListExtensionParam = new List<ExtensionParam>();
            ListMesData = new List<MesData>();
        }
        /// <summary>
        /// 接口名称
        /// </summary>
        public string Name { get; set; }
        /// <summary>
        /// 是否启用
        /// </summary>
        public bool Enabled { get; set; }
        /// <summary>
        /// Url接口地址
        /// </summary>
        public string Url { get; set; }
        /// <summary>
        /// 响应超时时间,单位ms
        /// </summary>
        public int ReceiveTimeout { get; set; }
        /// <summary>
        /// 接口用户名
        /// </summary>
        public string UserName { get; set; }
        /// <summary>
        /// 接口密码
        /// </summary>
        public string Password { get; set; }

        /// <summary>
        /// 参数集合
        /// </summary>
        public List<ExtensionParam> ListExtensionParam { get; set; }
        /// <summary>
        /// MES上传数据项集合
        /// </summary>
        public List<MesData> ListMesData { get; set; }
    }

    /// <summary>
    /// 接口扩展参数
    /// </summary>
    public class ExtensionParam
    {
        /// <summary>
        /// 参数键名
        /// </summary>
        public string Key { get; set; }
        /// <summary>
        /// 值
        /// </summary>
        public string Val { get; set; }
        /// <summary>
        /// 参数描述
        /// </summary>
        public string Des { get; set; }
    }
    
    /// <summary>
    /// 某一项数据上传参数
    /// </summary>
    public class MesData
    {
        /// <summary>
        /// 本地名称,一般为数据库表的字段名
        /// </summary>
        public string LocalName { get; set; }
        /// <summary>
        /// 本地描述
        /// </summary>
        public string LocalDescription { get; set; }
        /// <summary>
        /// MES名称
        /// </summary>
        public string MesName { get; set; }
        /// <summary>
        /// 数据类型
        /// </summary>
        public string DataType { get; set; }
        /// <summary>
        /// 单位
        /// </summary>
        public string Unit { get; set; }
        /// <summary>
        /// 上传的数据值
        /// </summary>
        public object Value { get; set; }
    }
}

Json读写操作类JsonFileUtil.cs如下:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO;
using Newtonsoft.Json;

namespace AutoSaveTreeNodeDataDemo
{
    public class JsonFileUtil
    {
        #region 配置文件读写

        /// <summary>
        /// 将配置对象写入程序执行目录指定名称的文件
        /// </summary>
        /// <param name="config">配置对象</param>
        /// <param name="strConfigFileFullPath">配置文件绝对路径</param>
        /// <returns></returns>
        public static string SaveConfig(object config, string strConfigFileFullPath, Encoding encoding = null)
        {
            string strRes = string.Empty;
            try
            {
                if (config == null)
                {          
                    if (File.Exists(strConfigFileFullPath))
                    {
                        File.Delete(strConfigFileFullPath);
                    }
                }
                //使用Json缩进
                string strJson = JsonConvert.SerializeObject(config, Formatting.Indented);
                if (encoding == null)
                {
                    encoding = Encoding.Default;
                }
                File.WriteAllText(strConfigFileFullPath, strJson, encoding);
            }
            catch (Exception ex)
            {
                strRes = ex.Message;
            }
            return strRes;
        }

        /// <summary>
        /// 读取配置文件的配置信息对象
        /// </summary>
        /// <typeparam name="T">泛型类型</typeparam>
        /// <param name="strConfigFileFullPath">配置文件的绝对路径</param>
        /// <returns></returns>
        public static T ReadConfig<T>(string strConfigFileFullPath, Encoding encoding) where T : class
        {
            T oRes = default(T);
            try
            {
                if (File.Exists(strConfigFileFullPath))
                {
                    string strJson = File.ReadAllText(strConfigFileFullPath, encoding);
                    if (!string.IsNullOrEmpty(strJson))
                    {
                        oRes = JsonConvert.DeserializeObject<T>(strJson);
                    }
                }
            }
            catch (Exception ex)
            {
                throw ex;
            }
            return oRes;
        }
        #endregion
    }
}

窗体FormSaveTreeNodeExchange.cs主要程序(忽略设计器自动生成的代码)如下:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace AutoSaveTreeNodeDataDemo
{
    public partial class FormSaveTreeNodeExchange : Form
    {
        /// <summary>
        /// 所有参数配置列表【成员变量】
        /// </summary>
        MesInterfaceConfig mesInterfaceConfig = new MesInterfaceConfig();
        /// <summary>
        /// 记录上一次被选中的节点,当上一个节点与本节点不一致时,保存上一个节点的内容到 缓存对象中
        /// </summary>
        TreeNode LastSelectedNode = null;
        /// <summary>
        /// 当前配置文件路径
        /// </summary>
        string curFilePath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "config.json");
        public FormSaveTreeNodeExchange()
        {
            InitializeComponent();

            //绑定数据源
            dgvcKey.DataPropertyName = "Key";
            dgvcVal.DataPropertyName = "Val";
            dgvcDes.DataPropertyName = "Des";

            dgvcLocalName.DataPropertyName = "LocalName";
            dgvcLocalDescription.DataPropertyName = "LocalDescription";
            dgvcMesName.DataPropertyName = "MesName";
            dgvcDataType.DataPropertyName = "DataType";
            dgvcUnit.DataPropertyName = "Unit";
            dgvcValue.DataPropertyName = "Value";
        }

        private void FormSaveTreeNodeExchange_Load(object sender, EventArgs e)
        {
            tvMesInterface.Nodes.Clear();
            mesInterfaceConfig = JsonFileUtil.ReadConfig<MesInterfaceConfig>(curFilePath, Encoding.UTF8);
            if (mesInterfaceConfig == null || mesInterfaceConfig.AllConfig.Count == 0)
            {
                MessageBox.Show($"致命错误:初始化失败,没有配置任何接口!请检查配置文件。\n{curFilePath}", "错误");
                return;
            }
            for (int i = 0; i < mesInterfaceConfig.AllConfig.Count; i++)
            {
                List<string> nameCollection = new List<string>();
                TreeNode treeNode = new TreeNode(mesInterfaceConfig.AllConfig[i].Name);
                tvMesInterface.Nodes.Add(treeNode);
            }
            tvMesInterface.ExpandAll();
        }

        private void tvMesInterface_AfterSelect(object sender, TreeViewEventArgs e)
        {
            ReadConfig(e.Node.Text);
            //记录选中的节点
            LastSelectedNode = e.Node;
        }

        /// <summary>
        /// 内部成员变量标记,确保BeforeSelect事件不会多次触发
        /// </summary>
        bool inside = false;
        private void tvMesInterface_BeforeSelect(object sender, TreeViewCancelEventArgs e)
        {
            if (!inside)
            {
                inside = true;
                if (LastSelectedNode != null && LastSelectedNode.Text != e.Node.Text)
                {
                    //如果上一次节点 与本次的节点不一致,就先保存上一次节点的内容到内存中
                    UpdateInterfaceInfo(LastSelectedNode.Text);
                }
                inside = false;
            }
        }

        /// <summary>
        /// 从内存中读取配置数据
        /// </summary>
        /// <param name="interfaceName"></param>
        private void ReadConfig(string interfaceName)
        {
            InterfaceConfig interfaceConfig = mesInterfaceConfig.AllConfig.Find(conf => conf.Name == interfaceName);

            chkEnabled.Checked = interfaceConfig.Enabled;
            txbName.Text = interfaceConfig.Name;
            txbUrl.Text = interfaceConfig.Url;
            txbReceiveTimeout.Text = interfaceConfig.ReceiveTimeout.ToString();
            txbUserName.Text = interfaceConfig.UserName;
            txbPassword.Text= interfaceConfig.Password;

            dgvExtensionParam.DataSource = interfaceConfig.ListExtensionParam;
            dgvMesData.DataSource = interfaceConfig.ListMesData;
        }

        /// <summary>
        /// 更新配置数据到内存中
        /// </summary>
        /// <param name="interfaceName"></param>
        private void UpdateInterfaceInfo(string interfaceName)
        {
            InterfaceConfig interfaceConfig = mesInterfaceConfig.AllConfig.Find(conf => conf.Name == interfaceName);

            interfaceConfig.Enabled = chkEnabled.Checked;
            interfaceConfig.Name = txbName.Text;
            interfaceConfig.Url = txbUrl.Text;
            interfaceConfig.ReceiveTimeout = int.Parse(txbReceiveTimeout.Text);
            interfaceConfig.UserName = txbUserName.Text;
            interfaceConfig.Password = txbPassword.Text;

            interfaceConfig.ListExtensionParam = new List<ExtensionParam>();
            for (int i = 0; i < dgvExtensionParam.Rows.Count; i++)
            {
                string key = Convert.ToString(dgvExtensionParam["dgvcKey", i].Value);
                string val = Convert.ToString(dgvExtensionParam["dgvcVal", i].Value);
                string des = Convert.ToString(dgvExtensionParam["dgvcDes", i].Value);
                interfaceConfig.ListExtensionParam.Add(new ExtensionParam()
                {
                    Key = key,
                    Val = val,
                    Des = des
                });
            }

            interfaceConfig.ListMesData = new List<MesData>();
            for (int i = 0; i < dgvMesData.Rows.Count; i++)
            {
                string localName = Convert.ToString(dgvMesData["dgvcLocalName", i].Value);
                string localDescription = Convert.ToString(dgvMesData["dgvcLocalDescription", i].Value);
                string mesName = Convert.ToString(dgvMesData["dgvcMesName", i].Value);
                string dataType = Convert.ToString(dgvMesData["dgvcDataType", i].Value);
                string unit = Convert.ToString(dgvMesData["dgvcUnit", i].Value);
                string value = Convert.ToString(dgvMesData["dgvcValue", i].Value);
                interfaceConfig.ListMesData.Add(new MesData()
                {
                    LocalName = localName,
                    LocalDescription = localDescription,
                    MesName = mesName,
                    DataType = dataType,
                    Unit = unit,
                    Value = value
                });
            }
        }

        private void btnClose_Click(object sender, EventArgs e)
        {
            this.Close();
        }

        private void btnSave_Click(object sender, EventArgs e)
        {
            UpdateInterfaceInfo(txbName.Text);
            string result = JsonFileUtil.SaveConfig(mesInterfaceConfig, curFilePath, Encoding.UTF8);
            if (result.Length == 0)
            {
                MessageBox.Show("保存配置成功", "提示");
            }
            else
            {
                MessageBox.Show($"保存配置失败.\n{result}", "提示");
            }
        }
    }
}

程序运行如图:

每切换一个树图节点,将自动保存上一次选中节点的内容到内存中,然后点击【保存】即可保存所有配置信息到Json文件。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

斯内科

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值