Winform 多个窗口编辑同一条数据同步的实现

摘要:
Frm公司。EditId=与所选数据行相对应的id;}无模式窗口是Form.Show();表单{publicForm1(){InitializeComponent();Form2frm=newForm2();表单{publicintpersonId;EventArgse){persons=XmlSerializeHelper.DeserializeObject<

场景: 一个主窗口中,可以在列表(DataGridView)里选中一条记录编辑,打开一个编辑窗口(非模态窗口),编辑窗口保存后需要刷新父窗口,由于编辑窗口是非模态窗口,如果打开了多个窗口,并且都是编辑同一条数据,那么一个窗口保存(并关闭)后,需要通知其它正在打开的窗口“数据有更改,需要刷新”

首先,刷新父窗口,如果是打开编辑窗口是模态窗口,那么可以类似如下的实现(伪代码):

FormEdit frm = new FormEdit();
frm.EditId = 选中数据行对应的id;    
if(frm.ShowDialog() == DialogResult.OK)
{
    UpdateThisForm();
}

非模态窗口是Form.Show();   由于该方法是void修饰,因此不能像上面那样去实现,此时可以在编辑窗口类中公开一个事件,当父窗口new这个编辑窗口后,可以注册这个事件,然后编辑窗口中如果保存了可以调用该事件方法达到通知的效果。

下面是例子,主窗口有一个DataGridView控件,数据绑定是Person的集合,Person实体类有Id,Name属性,选中某一行并点击编辑,可以打开编辑界面; 编辑界面有一个文本框显示编辑Person的Name,有一个保存按钮,点击保存之后将修改的Name更新到Person集合中(此处Person集合通过Xml序列化和反序列化实现保存于读取)

Winform 多个窗口编辑同一条数据同步的实现第1张

 

Winform 多个窗口编辑同一条数据同步的实现第2张

 

 主窗口核心代码:

Winform 多个窗口编辑同一条数据同步的实现第3张Winform 多个窗口编辑同一条数据同步的实现第4张
public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            if (dataGridView1.SelectedRows.Count == 1)
            {
                int personId = (int)dataGridView1.SelectedRows[0].Cells["Id"].Value;
                Form2 frm = new Form2();
                frm.personId = personId;
                frm.UpdateParentEvent += Frm_UpdateParentEvent;
                frm.Show();
            }
        }

        private void Frm_UpdateParentEvent()
        {
            LoadData();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            LoadData();
        }

        private void LoadData()
        {
            List<Person> personList = XmlSerializeHelper.DeserializeObject<List<Person>>("persons.xml");
            dataGridView1.DataSource = personList;
        }
View Code

 

编辑窗口核心代码:

Winform 多个窗口编辑同一条数据同步的实现第3张Winform 多个窗口编辑同一条数据同步的实现第6张
public partial class Form2 : Form
    {
        public int personId;
        /// <summary>
        /// 刷新父窗口的事件
        /// </summary>
        public event Action UpdateParentEvent;

        private Person p = null;

        private List<Person> persons;
        public Form2()
        {
            InitializeComponent();
        }

        private void Form2_Load(object sender, EventArgs e)
        {
            persons = XmlSerializeHelper.DeserializeObject<List<Person>>("persons.xml");
            p = persons.Where(ps => ps.Id == personId).SingleOrDefault();
            if (p != null)
            {
                txtName.Text = p.Name;
            }
        }

        private void btnSave_Click(object sender, EventArgs e)
        {
            if (p != null)
            {
                p.Name = txtName.Text;
                XmlSerializeHelper.SerializeObject(persons, "persons.xml");
                UpdateParentEvent?.Invoke();
                //获取所有打开的窗口
                var openForms = Application.OpenForms;
                Type thisType = this.GetType();
                this.Close();
                foreach (var item in openForms)
                {
                    Type itemType = item.GetType();
                    //如果都是当前窗口的类的实例,但不是当前实例(证明打开了多个窗口)
                    if (itemType == thisType && !object.ReferenceEquals(item,this))
                    {
                        int itemPersonId = (int)itemType.GetField("personId").GetValue(item);
                        //证明编辑的是同一条记录,需要通知其它窗口刷新页面
                        if (itemPersonId == this.personId)
                        {
                            MethodInfo mInfo = itemType.GetMethod("ChangeHandle",BindingFlags.NonPublic | BindingFlags.Instance);
                            mInfo?.Invoke(item,null);
                        }

                    }
                }
            }

        }

        private void ChangeHandle()
        {
            if (MessageBox.Show("其它窗口修改了本条数据,需要重新加载","提示",MessageBoxButtons.OK,MessageBoxIcon.Information) == DialogResult.OK)
            {
                //重新加载数据
                Form2_Load(this, null);
            }
        }
    }
View Code

测试:

下面是打开了两个编辑窗口,并且都是编辑同一条数据,当编辑其中一个的Name,并保存后,另一个提示需要刷新

Winform 多个窗口编辑同一条数据同步的实现第7张

 

 

示例中使用了Application.OpenForms;得到当前所有打开的窗口,遍历并通过反射获取她们的“类型”(Type,下同),如果“类型”与当前窗口的“类型”相同,并且不是当前窗口,且又是编辑同一条数据时,反射获取方法并调用,以达到通知的效果。

 

免责声明:文章转载自《Winform 多个窗口编辑同一条数据同步的实现》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇Oracle字符串拼接小记 TypeScript 中的循环引用问题下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

串行通信协议——基础知识

基础知识: 微型计算机中,通信有两种方式:串行通信、并行通信 1)串行通信       串行通信是指计算机与IO设备之间数据传输的各位是按顺序逐位进行传送,通常数据在一根数据线上传输。传输速度慢,传输设备成本低,适合远程通信,但是一些差分串行通信总线(RS-485,USB等)传输距离远,抗干扰强,速度也较快。 2)并行通信   指通过多条传输线交换数据,数...

OpenTelemetry架构介绍

OpenTelemetry: 经得起考验的工具 摘自:https://blog.newrelic.com/product-news/what-is-opentelemetry/ 目录 OpenTelemetry: 经得起考验的工具 什么是OpenTelemetry?术语 OpenTelemetry的好处 如何使用OpenTelemetry Op...

Excel 数据对比,窗口并列排序操作(xlw文件格式的由来)

步骤1:打开Excel文件,输入一些数据 步骤2:点击视图,创建新窗口(这里就会创建一个和步骤1一抹一样的的表格,我们可以在任务栏上看到) 第三步:点击视图里面的全部重排按钮,在重拍窗口里面选择需要拍了的方式(自己选择,这里我选择垂直并排) 到这来,两个一模一样的垂直的窗口就显示出来了,如下所示 补充说明:如果我们想下次打开这个文件还是这种垂直并排...

js数组删除(splice和delete)

最近一直在写js的数组,然后就发现了很奇怪的问题,后来才发现了规律。 删除数据的一行,一般有两种方法,一个是splice,一个是delete; splice:删除了数组后,数组的长度会自动变化。用法:arr.splice(2,1)——2是数组的下标值,1 代表输出一行数据。 delete: 删除了数组后,数组的长度不会变化。 用法:delete arr[2...

(转)大型分布式网站架构技术总结

本文是学习大型分布式网站架构的技术总结。对架构一个高性能,高可用,可伸缩,可扩展的分布式网站进行了概要性描述,并给出一个架构参考。一部分为读书笔记,一部分是个人经验总结。对大型分布式网站架构有很好的参考价值。   本次分享大纲如下 大型网站的特点 大型网站架构目标 大型网站架构模式 高性能架构 高可用架构 可伸缩架构 可扩展架构 安全架构 敏捷架构 大型架...

使用HttpURLConnection通过post请求服务器时,URLEncode编码的必要性

通过Post提交表单数据时,数据类型为x-www-urlencoded,提交到服务器的数据服务器默认是通过URLEncoder.encode()编码过得,所以服务器处理时会用URLDecoder.decode(s)进行解码,此时传输的数据就不能包括一些特殊字符。如+、%2b原因:通过URLEncoder.encode()空格会被编码成+号,+号会被编码成%...