场景: 一个主窗口中,可以在列表(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 == )
{
int personId = (int)dataGridView1.SelectedRows[].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;
}

编辑窗口核心代码:

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);
}
}
}

测试:

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

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

Winform 多个窗口编辑同一条数据同步的实现的更多相关文章

  1. easyUI dialog打开对话框,显示列表数据,选取一条数据操作后赋值给父窗口 resultMap声明为全局,生成getset方法

    <%@ page language="java" import="java.util.*" pageEncoding="UTF-8" ...

  2. easyui分页,编辑datagrid某条数据保存以后跳转到某一页

    参考资料:http://caizhilin2010.iteye.com/blog/1731698 问题:商品列表页面采用easyui的datagrid展示数据,编辑某行数据保存以后,要求跳转到 用户在 ...

  3. easyui datagrid 每条数据后添加操作按钮

    easyui datagrid 每条数据后添加“编辑.查看.删除”按钮 1.给datagrid添加操作字段:字段值 <table class="easyui-datagrid" ...

  4. 新建一个DataTable如何手动给其添加多条数据!

    早晨起来,想起昨天利用winform做类似于sqlserver数据库导入数据功能的时候,用到了新建一个DataTable手动给其添加多条数据,平时用不到,需要的时候想不起来了,这次不妨把他记下来.以下 ...

  5. vim 多窗口编辑

    本文出自   http://blog.csdn.net/shuangde800 ------------------------------------------------------------ ...

  6. DataTable相关操作,筛选,取前N条数据,获取指定列数据

    DataTable相关操作,筛选,取前N条数据,获取指定列数据2013-03-12 14:50 by Miracle520, 2667 阅读, 0 评论, 收藏, 编辑 1 #region DataT ...

  7. 解决:编辑一条彩信,附件选择添加音频,返回到编辑界面选择play,不能播放,没有声音

    [操作步骤]:编辑一条彩信,附件选择添加音频(外部音频),返回到编辑界面选择play,菜单键选择view slideshow [测试结果]:不能播放,没有声音 [预期结果]:可以播放 根据以往的经验( ...

  8. WinForm ListView不分页加载大量数据

    WinForm的ListView在加载大量数据时会出现闪烁的问题,同时数据加载很慢.如果你的列表中有超过千条的数据且不做特殊处理还是用普通的ListView.Items.Add(),估计你的用户得抱怨 ...

  9. 一条数据的HBase之旅,简明HBase入门教程-Write全流程

    如果将上篇内容理解为一个冗长的"铺垫",那么,从本文开始,剧情才开始正式展开.本文基于提供的样例数据,介绍了写数据的接口,RowKey定义,数据在客户端的组装,数据路由,打包分发, ...

随机推荐

  1. Mysql的预编译和批处理

    MySQL的预编译功能 预编译的好处 大家平时都使用过JDBC中的PreparedStatement接口,它有预编译功能.什么是预编译功能呢?它有什么好处呢? 当客户发送一条SQL语句给服务器后,服务 ...

  2. java-jdk7-forkjoin带有返回值

    来自并发编程网: http://ifeve.com/fork-join-3/ 如果这个任务必须解决一个超过预定义大小的问题,你应该将这个任务分解成更多的子任务,并且用Fork/Join框架来执行这些子 ...

  3. C语言理论知识

    C语言-----理论部分   一:软件开发概述1.程序语言的发展:机器语言-->汇编语言-->高级语言.2.软件开发的基本步骤与方法:分析问题,建立数学模型-->确定数据结构和算法- ...

  4. Ruby语言学习系列--String 类函数

        函数名称 说明 示例 * 将字符串拷贝N次 “ha”*4    >> “hahahaha” + <<  concat 连接字符串 “yes” + “no”  >& ...

  5. SpringMVC源码阅读:Json,Xml自动转换

    1.前言 SpringMVC是目前J2EE平台的主流Web框架,不熟悉的园友可以看SpringMVC源码阅读入门,它交代了SpringMVC的基础知识和源码阅读的技巧 本文将通过源码(基于Spring ...

  6. msdn 中MethodBase.Invoke 方法 介绍中的坑

    模块开发总结: c#动态调用webservices 来自网络及使用心得. msdn: MethodBase.Invoke 方法 (Object, Object[]) 使用指定的参数调用当前实例所表示的 ...

  7. Angular待办事项应用3

    隔离业务逻辑 接着上一节,业务逻辑应该复古牛仔单独的service中,我们在todo文件夹中建立TodoService ng g s todo/todo 引入UUID包 todo中id要唯一,一个是采 ...

  8. XP系统运行wpf程序出现透明现象的解决

    xp 虚拟机运行WPF程序的时候,有部分控件透明,在这儿有一个可能的解决方案: 关闭系统的硬件加速: 1. 按“WIN” + R 键,在“运行”输入框中输入“dxdiag”: 2. 在“DirectX ...

  9. JS中的事件冒泡——总结

    一. 有话要说 事件冒泡这个话题已经被园子里的朋友说透了,已经没什么要讲的了,但是由于呢我这边有个小问题刚好跟这个事件冒泡有关,就突然性想写个总结:一方面是给自己增加印象,另一方面给园子的新手们,提供 ...

  10. [Linux] Linux系统(进程管理)

    进程:当我们运行程序时,Linux会为程序创建一个特殊的环境,包含程序运行的所有资源,这个环境就称为进程 前台进程:一般我们使用一些命令,都属于前台进程,直接输出结果到显示器 后台进程:在命令的末尾加 ...