在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. jquery插件:仿百度首页可展开收起的消息提示控件

    消息提示插件大伙并不陌生了,无论是个系统还是网站,基本都要有消息系统.但我认为,一个好的提示插件应当具备很好的独立性,不与页面其他元素发生任何关系,其次是能对外提供丰富的接口,因为你生来就是被别人来调 ...

  2. DDD领域驱动设计之聚合、实体、值对象

    关于具体需求,请看前面的博文:DDD领域驱动设计实践篇之如何提取模型,下面是具体的实体.聚合.值对象的代码,不想多说什么是实体.聚合等概念,相信理论的东西大家已经知晓了.本人对DDD表示好奇,没有在真 ...

  3. Java-字符串练习

    1. 用自己的算法实现startsWith和endsWith功能. String str="dsjhajdl"; Scanner sc=new Scanner(System.in) ...

  4. Java-数组练习4

    16.按要求编写Java应用程序.编写一个名为Test的主类,类中只有一个主方法: 在主方法中定义一个大小为50的一维整型数组,数组名为x,数组中存放着{1, 3,5,…,99}输出这个数组中的所有元 ...

  5. H5常用代码:适配方案3

    在H5项目中有一种常见的宣传页,就是那种整屏整屏的,带着炫丽进场动画的移动宣传页,不仅是一种欣赏也起到了很大宣传作用. 对于这种整屏的适配,前面通过视口的兼容处理也是可以做到的,但是在窄屏下会在上下有 ...

  6. Node.js入门:前后端模块的异同

        通常有一些模块可以同时适用于前后端,但是在浏览器端通过script标签的载入JavaScript文件的方式与Node.js不同.Node.js在载入到最终的执行中,进行了包装,使得每个文件中的 ...

  7. apache2添加模块和添加站点

    apache2添加模块和添加站点 linux下的apache2的目录和windows上的区别还是很大的,但是用起来却更方便了,详解请看另一篇文章http://www.cnblogs.com/wancy ...

  8. android 股票数据通过日K获取周K的数据 算法 源码

    目前的数据是从新浪接口获取的, http://biz.finance.sina.com.cn/stock/flash_hq/kline_data.php?symbol=sh600000&end ...

  9. Java基础-继承-编写一个Java应用程序,设计一个汽车类Vehicle,包含的属性有车轮个数 wheels和车重weight。小车类Car是Vehicle的子类,其中包含的属性有载人数 loader。卡车类Truck是Car类的子类,其中包含的属性有载重量payload。每个 类都有构造方法和输出相关数据的方法。最后,写一个测试类来测试这些类的功 能。

    #29.编写一个Java应用程序,设计一个汽车类Vehicle,包含的属性有车轮个数 wheels和车重weight.小车类Car是Vehicle的子类,其中包含的属性有载人数 loader.卡车类T ...

  10. Spring注意事项(各部分理解)

    (1),每一个bean属性,就是一个普通的java类. 类有属性,有方法,如何交给容器管理.(注解的方式,xml方式配置) (2),通过Bean来实例化对象的方式 1.通过构造器(一般是无参的默认构造 ...