在Winform界面中窗体我们一般使用多文档进行展示,也就是类似一般的选项卡的方式可以加载多个窗体界面。一般来说,我们如果打开新的窗体,给窗体传递参数是很容易的事情,但是在框架层面,一般的窗体是通过动态创建的,一般传入窗体的类型,在多文档集合里面判断,如果存在则激活,如果不存在则创建的方式,所以我们传递参数会碰到一些问题。本文即使介绍如何在这种方式下,给窗体对象传递参数,从而实现相应的数据处理功能。

不管是主体界面中,左侧包含树形列表,还是顶部包含工具栏的情况,都可能涉及打开窗体的时候,传递一些初始化参数,方便窗体的更新显示的情况,这种的处理相对直接传值的方式需要复杂一点,我们可以通过接口、事件的方式进行处理,下面我来介绍一下整个实现的方式。

1、多文档窗体的构建或者激活

在我的Winform开发框架里面,我们加载多文档窗体的时候,都是统一采用一种方式来进行构建不存在或者激活已有窗体的,代码如下所示。

        private void tool_Purchase_ItemClick(object sender, DevExpress.XtraBars.ItemClickEventArgs e)
{
ChildWinManagement.LoadMdiForm(this, typeof(FrmPurchase));
} private void tool_TakeOut_ItemClick(object sender, DevExpress.XtraBars.ItemClickEventArgs e)
{
ChildWinManagement.LoadMdiForm(this, typeof(FrmTakeOut));
} private void tool_StockSearch_ItemClick(object sender, DevExpress.XtraBars.ItemClickEventArgs e)
{
ChildWinManagement.LoadMdiForm(this, typeof(FrmStockSearch));
}

而这个LoadMdiForm的函数,主要判断多文档集合里面是否有对应的对象,没有这创建,有则激活显示即可,代码如下所示。

        /// <summary>
/// 唯一加载某个类型的窗体,如果存在则显示,否则创建。
/// </summary>
/// <param name="mainDialog">主窗体对象</param>
/// <param name="formType">待显示的窗体类型</param>
/// <param name="json">传递的参数内容,自定义Json格式</param>
/// <returns></returns>
public static Form LoadMdiForm(Form mainDialog, Type formType, string json)
{
bool bFound = false;
Form tableForm = null;
foreach (Form form in mainDialog.MdiChildren)
{
if (form.GetType() == formType)
{
bFound = true;
tableForm = form;
break;
}
}
if (!bFound)
{
tableForm = (Form) Activator.CreateInstance(formType);
tableForm.MdiParent = mainDialog;
tableForm.Show();
} tableForm.BringToFront();
tableForm.Activate(); return tableForm;
}

这种方式构建的多文档界面如下所示。

2、多文档窗体传参数的实现处理

首先,为了实现这个方式,我们需要先创建一个接口,是我们窗体界面的基类,实现这个接口,然后在加载的时候,转换为对应的接口处理就可以了,具体接口代码如下所示。

    /// <summary>
/// 使用ChildWinManagement辅助类处理多文档加载的窗体,在构建或激活后,触发一个通知窗体的事件,方便传递相关参数到目标窗体。
/// 为了更加通用的处理,传递的参数使用JSON定义格式的字符串。
/// </summary>
public interface ILoadFormActived
{
/// <summary>
/// 窗体激活的事件处理
/// </summary>
/// <param name="json">传递的参数内容,自定义JSON格式</param>
void OnLoadFormActived(string json);
}

这里参数为了通用,我们定义为字符串的JSON内容,方便实现更加强大的参数处理。

修改好这些,我们需要在基类窗体 BaseForm 实现这个增加的接口,如下所示。

    /// <summary>
/// 常规界面基类
/// </summary>
public partial class BaseForm : XtraForm, IFunction, ILoadFormActived

实现这个接口很容易,为了更加方便业务窗体(继承自基类窗体BaseForm),我们提供一个事件进行处理,具体代码如下所示。

    /// <summary>
/// 常规界面基类
/// </summary>
public partial class BaseForm : DevExpress.XtraEditors.XtraForm, IFunction, ILoadFormActived
{
/// <summary>
/// 定义一个窗体激活后的处理委托类型
/// </summary>
/// <param name="json"></param>
public delegate void FormActiveHandler(string json);
/// <summary>
/// 使用ChildWinManagement辅助类处理多文档加载的窗体,在构建或激活后,触发一个通知窗体的事件,方便传递相关参数到目标窗体。
/// 为了更加通用的处理,传递的参数使用JSON定义格式的字符串。
/// </summary>
public event FormActiveHandler LoadFormActived;

同时,我们实现接口,就是直接调用事件就可以了,具体代码如下所示。

        /// <summary>
/// 窗体激活的事件处理
/// </summary>
/// <param name="json">传递的参数内容,自定义JSON格式</param>
public virtual void OnLoadFormActived(string json)
{
//默认什么也没做
//如果需要处理传参数,则在这里处理参数Json即可
if (LoadFormActived != null)
{
LoadFormActived(json);
}
}

这样我们就完成了基类窗体的处理了,前面我们介绍了动态构建加载窗体的时候,是使用了LoadMdiForm的函数,既然我们的接口实现了上面的ILoadFormActived接口,那么我们动态创建或者激活窗体的时候,那么就使用这个接口进行处理一下,以便实现对应事件的处理操作了。因此我们的窗体加载函数修改代码,如下所示。

        /// <summary>
/// 唯一加载某个类型的窗体,如果存在则显示,否则创建。
/// </summary>
/// <param name="mainDialog">主窗体对象</param>
/// <param name="formType">待显示的窗体类型</param>
/// <param name="json">传递的参数内容,自定义Json格式</param>
/// <returns></returns>
public static Form LoadMdiForm(Form mainDialog, Type formType, string json)
{
bool bFound = false;
Form tableForm = null;
foreach (Form form in mainDialog.MdiChildren)
{
if (form.GetType() == formType)
{
bFound = true;
tableForm = form;
break;
}
}
if (!bFound)
{
tableForm = (Form) Activator.CreateInstance(formType);
tableForm.MdiParent = mainDialog;
tableForm.Show();
} //窗体激活的时候,传递对应的参数信息
ILoadFormActived formActived = tableForm as ILoadFormActived;
if (formActived != null)
{
formActived.OnLoadFormActived(json);
} tableForm.BringToFront();
tableForm.Activate(); return tableForm;
}

还记得我们前面打开一个多文档窗体的代码,就是利用这个接口进行创建或者激活指定类型的窗体的,如下所示。

ChildWinManagement.LoadMdiForm(this, typeof(FrmItemDetail));

那么我们增加了新的函数参数Json后,我们如果需要传递一个指定的参数给对应的窗体,那么就修改下调用即可。例如下面,为了测试,我传入一个动态构建的类信息,然后转换为Json字符串信息给接收窗体,并进行加载窗体。

            //使用自定义参数调用
var obj = new { ItemNo = "", ItemName = "测试名称" };
var param = JsonConvert.SerializeObject(obj, Formatting.Indented); ChildWinManagement.LoadMdiForm(this, typeof(FrmItemDetail), param);

前面我们介绍了基类窗体,已经实现定义了一个事件,并对这些通知的接口进行处理,具体如下所示。

那么我们前面加载的 FrmItemDetail  需要做哪些工作呢,就是实现对事件的处理即可,如下所示。

这样我们就能够通过实现对应的事件,把整个通知事件的处理处理完毕了,我们来看看最终的界面效果,如下所示,接收到的窗体事件后,会弹出一个提示对话框在右下角了。

当然实际上我们可以做的更多,如可以传递一些具体的信息,让它在界面上进行显示。

如其中一个客户基于我的Winform开发框架基础上进行的参数传递案例界面如下所示。

本文只是对其中在框架层面对不同多文档窗体的传值进行的一个研究探索和实现,其中的理念是基于常用的接口和事件驱动的方式进行处理,以期达到方便、高效的目的,如果您有更好的建议,也希望多多交流。

在Winform界面中实现对多文档窗体的参数传值的更多相关文章

  1. Winform开发框架中的内容及文档管理模块功能介绍

    在开发项目的时候,我们有一些场景需要编辑一些HTML文档,作为内容发布系统的一部分,有时候也需要对一些文档如WORD文档进行编辑管理,这样需要我们对这些内容及文档进行合适的管理.本文主要介绍在WInf ...

  2. 如何在ASP.NET Core 中快速构建PDF文档

    比如我们需要ASP.NET Core 中需要通过PDF来进行某些简单的报表开发,随着这并不难,但还是会手忙脚乱的去搜索一些资料,那么恭喜您,这篇帖子会帮助到您,我们就不会再去浪费一些宝贵的时间. 在本 ...

  3. Springboot中整合knife4j接口文档

    在项目开发过程中,web项目的前后端分离开发,APP开发,需要由前端后端工程师共同定义接口,编写接口文档,之后大家都根据这个接口文档进行开发. 什么是knife4j 简单说knife4j就swagge ...

  4. 在我的电脑中删除wps云文档图标

    在我的电脑中删除wps云文档图标 右键点击win10左下角选择运行,输入regedit打开注册表后,找到以下注册表路径: HKEY_CURRENT_USER\Software\Microsoft\Wi ...

  5. Elasticsearch中最重要的文档CRUD要牢记

    Elasticsearch文档CRUD要牢记 转载参考:https://juejin.im/post/5ddbf298e51d4523053c42e7 在Elasticsearch中,文档(docum ...

  6. MDI-多文档窗体

    1.IsMdicontainer属性设置是否为多文档窗体 this.IsMdiContainer = true; 2.MdiParent属性设置为父窗体 Frm_Child frm = new Frm ...

  7. Winform界面中主从表编辑界面的快速处理

    在Winform开发中,我们往往除了常规的单表信息录入外,有时候设计到多个主从表的数据显示.编辑等界面,单表的信息一般就是控件和对象实体一一对应,然后调用API保存即可,主从表就需要另外特殊处理,本随 ...

  8. Winform界面中实现菜单列表的动态个性化配置管理

    在我们一般的应用系统里面,由于系统是面向不同类型的用户,我们所看到的菜单会越来越多,多一点的甚至上百个,但是我们实际工作接触的菜单可能就是那么几个,那么对于这种庞大的菜单体系,寻找起来非常不便.因此对 ...

  9. Winform界面中实现通用工具栏按钮的事件处理

    在一个给客户做的项目中,界面要求修改增加通用工具栏按钮的事件处理,也就是在主界面中放置几个固定的功能操作按钮,打开不同的页面的时候,实现对应页面的功能处理,这种和我标准的界面处理方式有所不同,标准的列 ...

随机推荐

  1. 【译】AS3利用CPU缓存

    利用CPU缓存   计算机有随机存取存储器RAM(译注:即我们常说的内存),但有更快形式的存储器.如果你希望你的应用程序的快速运行,你需要知道这些其他的存储器.今天的文章中讨论了它们,并给出了两个AS ...

  2. 用批处理文件进行TCP/IP设置,方便在家与办公IP切换

    在公司用公司分配的固定IP上网,回家后又要将本本设置为家里的固定IP上网,每次都要手动重复一个过程: 打开网络中心,选择本地连接,进入属性然后选择IPV4进行TCP/IP的设置,填入IP,子网掩码DN ...

  3. Java8的新特性以及与C#的比较

    函数式接口 VS 委托 在C中,可以使用函数指针来存储函数的入口,从而使得函数可以像变量一样赋值.传递和存储,使得函数的调用变得十分灵活,是实现函数回调的基础.然而函数指针不存在函数的签名信息,甚至可 ...

  4. IOS 推送-配置与代码编写

    IOS 推送配置与代码编写 这里介绍IOS的推送,本文章已经在IOS6/7/8上都能运行OK,按照道理IOS9应该没问题. 大纲: 1.文章前提 2.推送介绍 3.推送文件账号设置 4.推送证书介绍 ...

  5. Atitit. Atiposter 发帖机 新特性 poster new feature v11  .docx

    Atitit. Atiposter 发帖机 新特性 poster new feature v11  .docx 1.1.  版本历史1 2. 1. 未来版本规划2 2.1. V12版本规划2 2.2. ...

  6. Atitit usrQBM2331 参数格式化规范

    Atitit usrQBM2331 参数格式化规范 String sql = "insert agent(uid,parent_id,pwd,name,tel,wechat,bkkad,si ...

  7. Atitit 异常的实现原理 与用户业务异常

    Atitit 异常的实现原理 与用户业务异常 1.1. 异常的实现原理1 1.2. 用户业务异常1 1.3. 异常转译和异常链2 1.4. 避免异常2 1.5. 异常恢复3 1.6. catch代码块 ...

  8. fir.im Weekly - 可能是 iOS 审核最全面的解决方案

    ipv6 被拒绝,后台定位被拒绝--让很多国内 iOS 开发者心力交瘁.这是一份关于 iOS 审核的终极免费方案,作者iOSWang对最近iOS 审核被拒问题给出了比较全面的方案:Solve-App- ...

  9. hdu4292Food(最大流Dinic算法)

    /* 题意:每一个人都有喜欢的吃的和喝的,每一个人只选择一个数量的吃的和一个数量的喝的,问能满足最多的人数!? 思路:建图很是重要!f-food, p-people, d-drink 建图: 0(源点 ...

  10. java中Object.equals()简单用法

    /* equals()方法默认的比较两个对象的引用! */ class Child { int num; public Child(int x){ num = x; } //人文的抛出运行时异常的好处 ...