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,下同),如果“類型”與當前窗口的“類型”相同,並且不是當前窗口,且又是編輯同一條數據時,反射獲取方法並調用,以達到通知的效果。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM