zoukankan      html  css  js  c++  java
  • Winform 多个窗口编辑同一条数据同步的实现

    场景: 一个主窗口中,可以在列表(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序列化和反序列化实现保存于读取)

     

     

     主窗口核心代码:

    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

     

    编辑窗口核心代码:

    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,并保存后,另一个提示需要刷新

     

     

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

     

  • 相关阅读:
    [CodeForces]Codeforces Round #429 (Div. 2) ABC(待补)
    About Me
    2018-06-14
    Codeforces Codeforces Round #484 (Div. 2) E. Billiard
    Codeforces Codeforces Round #484 (Div. 2) D. Shark
    Codeforces Educational Codeforces Round 44 (Rated for Div. 2) F. Isomorphic Strings
    Codeforces Educational Codeforces Round 44 (Rated for Div. 2) E. Pencils and Boxes
    Codeforces Avito Code Challenge 2018 D. Bookshelves
    Codeforces Round #485 (Div. 2) D. Fair
    Codeforces Round #485 (Div. 2) F. AND Graph
  • 原文地址:https://www.cnblogs.com/godbell/p/7583116.html
Copyright © 2011-2022 走看看