Winform 多個窗口編輯同一條數據同步的實現
阿新 • • 發佈:2017-09-24
load message mes save http 有一個 9.png 實例 使用
場景: 一個主窗口中,可以在列表(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,下同),如果“類型”與當前窗口的“類型”相同,並且不是當前窗口,且又是編輯同一條數據時,反射獲取方法並調用,以達到通知的效果。
Winform 多個窗口編輯同一條數據同步的實現