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

在一个给客户做的项目中,界面要求修改增加通用工具栏按钮的事件处理,也就是在主界面中放置几个固定的功能操作按钮,打开不同的页面的时候,实现对应页面的功能处理,这种和我标准的界面处理方式有所不同,标准的列表界面,一般在界面中放置了一些常规的按钮,如查询/更新、新建、编辑、删除、导入、导出等常规操作,现在是需要把这些提升到主界面的层次上放置按钮,这种处理方式也算是提供一种方便吧。本篇随笔介绍实现这个功能的思路和代码实现逻辑。

1、界面功能介绍

这里要实现的通用工具栏按钮的事件处理,具体的界面是这样的,我们处于一个多文档的主界面中,在主界面的顶部工具栏放置这些通用的工具栏按钮,以便提高相关的处理便利和效率。

从上面的界面我们可以看到,程序主界面的顶部工具栏上有一些常规的操作,包括如查询、新建、编辑、删除、导入、导出等按钮,可以为程序的功能操作提供方便。

当我们打开一个新的窗体页面,那么对应的按钮事件也应该和这个窗体相关,或者我们切换到其他窗体,那么按钮的处理事件也应该跟着变化到对应的窗体上,这种就是我们需要的效果。

上面的逻辑也就是我们新建一个窗体、或者切换一个窗体,那么需要通知顶部工具栏进行更新或者进行一个对接的处理才可以。

2、界面窗体基类的处理

由于我们想尽可能的减少开发的工作量,因此希望在基类进行一些事件或者接口的封装,以便降低新建列表窗体的时候的代码编写。

对于一个如查询操作的处理事件,我们需要定义一个接口来实现这个功能,这样我们才可以在打开的窗体的时候,把它转换为对应的接口处理。

例如我们定义一个IMenuAction的接口,以更新事件为例,需要实现三部分的接口,一个是事件定义,一个是判断是否包含更新事件,一个是具体的处理逻辑。

    /// <summary>
    /// 定义菜单中的通用按钮事件
    /// </summary>
    public interface IMenuAction
    {
        /// <summary>
        /// 更新按钮事件
        /// </summary>
        event EventHandler Refresh_MenuEvent;

        /// <summary>
        /// 是否包含更新事件
        /// </summary>
        bool HasEventRefresh { get; }

        /// <summary>
        /// 更新操作
        /// </summary>
        void ProcessRefresh(object sender, EventArgs e);

对于其他总共6个标准的按钮事件处理,我们也同样一样定义,那么整个IMenuAction的接口定义如下所示。

    /// <summary>
    /// 定义菜单中的通用按钮事件
    /// </summary>
    public interface IMenuAction
    {
        /// <summary>
        /// 更新按钮事件
        /// </summary>
        event EventHandler Refresh_MenuEvent;
        /// <summary>
        /// 新建按钮事件
        /// </summary>
        event EventHandler Add_MenuEvent;
        /// <summary>
        /// 编辑按钮事件
        /// </summary>
        event EventHandler Edit_MenuEvent;
        /// <summary>
        /// 删除按钮事件
        /// </summary>
        event EventHandler Delete_MenuEvent;
        /// <summary>
        /// 导入按钮事件
        /// </summary>
        event EventHandler Import_MenuEvent;
        /// <summary>
        /// 导出按钮事件
        /// </summary>
        event EventHandler Export_MenuEvent;

        /// <summary>
        /// 是否包含更新事件
        /// </summary>
        bool HasEventRefresh { get; }
        /// <summary>
        /// 是否包含增加事件
        /// </summary>
        bool HasEventAdd { get; }
        /// <summary>
        /// 是否包含编辑事件
        /// </summary>
        bool HasEventEdit { get; }
        /// <summary>
        /// 是否包含删除事件
        /// </summary>
        bool HasEventDelete { get; }
        /// <summary>
        /// 是否包含导入事件
        /// </summary>
        bool HasEventImport { get; }
        /// <summary>
        /// 是否包含导出事件
        /// </summary>
        bool HasEventExport { get; }

        /// <summary>
        /// 更新操作
        /// </summary>
        void ProcessRefresh(object sender, EventArgs e);
        /// <summary>
        /// 增加操作
        /// </summary>
        void ProcessAdd(object sender, EventArgs e);
        /// <summary>
        /// 编辑操作
        /// </summary>
        void ProcessEdit(object sender, EventArgs e);
        /// <summary>
        /// 删除操作
        /// </summary>
        void ProcessDelete(object sender, EventArgs e);
        /// <summary>
        /// 导入操作
        /// </summary>
        void ProcessImport(object sender, EventArgs e);
        /// <summary>
        /// 导出操作
        /// </summary>
        void ProcessExport(object sender, EventArgs e);
    }

那么对于列表界面的基类窗体,我们除了让他继承自XtraForm这个标准的窗体外,我们还让它实现对应的IMenuAction接口,如下是列表界面基类BaseDock的窗体定义。

    /// <summary>
    /// 用于一般列表界面的基类
    /// </summary>
    public partial class BaseDock : XtraForm, IMenuAction

那么这个BaseDock的基类需要实现那些通用按钮事件的接口,如下所示。

        #region 通用按钮菜单事件
        /// <summary>
        /// 更新按钮事件
        /// </summary>
        public event EventHandler Refresh_MenuEvent;
        /// <summary>
        /// 根据事件判断是否有
        /// </summary>
        public bool HasEventRefresh
        {
            get
            {
                return Refresh_MenuEvent != null;
            }
        }
        /// <summary>
        /// 调用事件定义
        /// </summary>
        public void ProcessRefresh(object sender, EventArgs e)
        {
            if (Refresh_MenuEvent != null)
            {
                Refresh_MenuEvent(sender, e);
            }
        }

        .......................

        #endregion

通过基类的这样处理,我们就可以在具体列表窗体里,赋值给对应的事件就可以了。

3、列表窗体界面的处理

例如我们处理一个应用菜单的列表管理界面,定义窗体如下所示,继承了我们所实现IMenuAction的基类BaseDock。

    /// <summary>
    /// 应用菜单管理
    /// </summary>
    public partial class FrmApplicationMenu : BaseDock

那么我们需要指定它的几个处理事件,初始化代码如下所示。

        /// <summary>
        /// 初始化公用菜单按钮的处理
        /// </summary>
        private void InitMenuAction()
        {
            this.Refresh_MenuEvent += (s, e) => { btnSearch_Click(s, e); };
            this.Add_MenuEvent += (s, e) => { btnAddNew_Click(s, e); };
            this.Edit_MenuEvent += (s, e) => { winGridViewPager1_OnEditSelected(s, e); };
            this.Delete_MenuEvent += (s, e) => { winGridViewPager1_OnDeleteSelected(s, e); };
            this.Import_MenuEvent += (s, e) => { btnImport_Click(s, e); };
            this.Export_MenuEvent += (s, e) => { btnExport_Click(s,e);};
        }

这样我们就知道对应接口是如何和具体的页面事件发生关系了。

4、主窗体界面的处理

我们在构建主界面的左侧功能树的时候,我们通过树列表的选中事件加载对应的窗体,具体代码如下所示。

    //处理树形菜单的点击操作,如果TAG存在,则解析并加载对应的页面到多文档里面
    treeView.AfterSelect += (sender, e) =>
    {
        string tag = e.Node.Tag as string;
        if (!string.IsNullOrEmpty(tag))
        {
            LoadPlugInForm(tag);
        }
    };

在这个函数里面,我们最终是通过配置动态构建对应的窗体,LoadPlugInForm逻辑的最终实现的部分代码如下所示。

    var form = LoadMdiForm(this.mainForm, objType, isShowDialog);
    RefreshButton(form);

这里我们构建窗体或者激活窗体都获得一个窗体对象,然后刷新功能按钮的状态处理即可。

    /// <summary>
    /// 更新按钮状态
    /// </summary>
    /// <param name="form">当前窗体</param>
    public void RefreshButton(Form form)
    {
        this.CurrentForm = form;
        IMenuAction action = form as IMenuAction;
        if (action != null)
        {
            //事件处理后再判断
            menuButton.refresh.Enabled = (action.HasEventRefresh);
            menuButton.add.Enabled = (action.HasEventAdd);
            menuButton.edit.Enabled = (action.HasEventEdit);
            menuButton.delete.Enabled = (action.HasEventDelete);
            menuButton.import.Enabled = (action.HasEventImport);
            menuButton.export.Enabled = (action.HasEventExport);
        }
    }

这样的处理,就可以实现了在主界面的多文档处理中,不管我们是新建一个列表窗体,还是激活切换到一个其他的窗体的时候,按钮的状态和对应的窗体绑定,实现随时更新显示。

当然通用工具栏按钮的事件我们需要初始化,它是根据当前选中的窗体进行统一的处理的,具体代码如下所示。

        /// <summary>
        /// 初始化菜单按钮的事件处理
        /// </summary>
        private void InitMenuEvent()
        {
            //事件绑定
            //先实现事件绑定
            menuButton.add.ItemClick += (s, e) =>
            {
                if (CurrentForm != null)
                {
                    IMenuAction action = CurrentForm as IMenuAction;
                    if (action != null)
                    {
                        action.ProcessAdd(s, e);
                    }
                }
            };
            menuButton.edit.ItemClick += (s, e) =>
            {
                if (CurrentForm != null)
                {
                    IMenuAction action = CurrentForm as IMenuAction;
                    if (action != null)
                    {
                        action.ProcessEdit(s, e);
                    }
                }
            };
            menuButton.delete.ItemClick += (s, e) =>
            {
                if (CurrentForm != null)
                {
                    IMenuAction action = CurrentForm as IMenuAction;
                    if (action != null)
                    {
                        action.ProcessDelete(s, e);
                    }
                }
            };
            menuButton.import.ItemClick += (s, e) =>
            {
                if (CurrentForm != null)
                {
                    IMenuAction action = CurrentForm as IMenuAction;
                    if (action != null)
                    {
                        action.ProcessImport(s, e);
                    }
                }
            };
            menuButton.export.ItemClick += (s, e) =>
            {
                if (CurrentForm != null)
                {
                    IMenuAction action = CurrentForm as IMenuAction;
                    if (action != null)
                    {
                        action.ProcessExport(s, e);
                    }
                }
            };
            menuButton.refresh.ItemClick += (s, e) =>
            {
                if (CurrentForm != null)
                {
                    IMenuAction action = CurrentForm as IMenuAction;
                    if (action != null)
                    {
                        action.ProcessRefresh(s, e);
                    }
                }
            };
        }

上面这个事件只需要绑定一次,不会造成按钮的事件多次绑定问题,虽然一次绑定,它的具体处理还是和当前窗体有关,它会把当前窗体转换为对应的IMenuAction接口,然后调用对应的处理函数实现功能的绑定。

以上就是我对于实现这种通用按钮事件处理的思路和具体逻辑代码,供大家参考学习,有错漏之处还请多多包涵。

本文转自博客园伍华聪的博客,原文链接:Winform界面中实现通用工具栏按钮的事件处理,如需转载请自行联系原博主。

时间: 2024-09-29 17:07:58

Winform界面中实现通用工具栏按钮的事件处理的相关文章

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

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

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

在我们一般的应用系统里面,由于系统是面向不同类型的用户,我们所看到的菜单会越来越多,多一点的甚至上百个,但是我们实际工作接触的菜单可能就是那么几个,那么对于这种庞大的菜单体系,寻找起来非常不便.因此对菜单的个性化配置就显得尤为重要,本篇随笔就是基于这样的理念,提供用户对可见菜单进行一个动态配置,只选自己喜欢.常用的菜单显示出来即可,菜单的配置存储在数据库里面,在不同的客户端体验都是一样.本篇随笔主要介绍实现这样的功能的一个完整思路,部分代码逻辑可供参考. 1. 菜单列表的动态个性化配置的过程 在

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

在Winform开发中,我们往往除了常规的单表信息录入外,有时候设计到多个主从表的数据显示.编辑等界面,单表的信息一般就是控件和对象实体一一对应,然后调用API保存即可,主从表就需要另外特殊处理,本随笔介绍如何快速实现主从表编辑界面的处理,结合GridControl控件的GridView控件对象,实现数据在列表中的实时编辑,非常方便. 1.主从表的界面设计及展示 主从表一般涉及两个以上的表,一个是主表,其他的是从表的,在实际情况下,一般包含两个表较多,我们这里以两个表的主从表关系进行分析处理.

请问mfc中如何实现工具栏按钮的自定义添加与删除

问题描述 请问mfc中如何实现工具栏按钮的自定义添加与删除 mfc单文档程序运行后,左上角有一个系统自动生成的工具栏,点击该工具栏右边的小倒三角形,会出现如下图所示的自定义添加或删除按钮的选项 现在我自己创建了一个工具栏,想实现上述功能,请问该怎么做?谢谢~~~ 解决方案 难道你的没有么?你可以试试BCGControlBar,它是CMFCxxx控件的商业完整版本.包含了和Office一样的自定义对话框,不需要写任何代码. 解决方案二: 需要用MFC等提供的框架,才会有,它帮你实现了.你自己创建的

请教如果在word2003中添加一个工具栏按钮(类似与金山词霸那样)

问题描述 请教如果在word2003中添加一个工具栏按钮(类似与金山词霸那样) 解决方案 解决方案二:想用C#代码实现,有难度,顶下吧,看高手怎么说的..

在jsp界面中如何设置一个按钮,点击可以选择文件夹路径

问题描述 就像安装软件选择文件夹路径一样,如何在jsp的页面中也实现这一功能,如果有参考代码最好了,谢谢! 解决方案 最简单的,用<input type="file" />解决方案二:可参考我的http://www.iteye.com/topic/1129224#2388407可以自己改造下当然也可以使用如http://www.uploadify.com/demos/

调整代码生成工具Database2Sharp的Winform界面生成,使其易于列表工具栏的使用

在Winform界面开发的时候,有时候我们客户喜欢把功能放在列表界面的顶部,这样界面和功能整齐放置,也是一种比较美观的方式,基于这种方式的考虑,改造了代码生成工具的Winform界面生成规则,把增删改查的常规处理功能抽取简化的函数,易于在实际项目中使用工具栏的方式处理. 1.常规的Winform界面 我们在之前的界面中,通常都是使用一些按钮,以及右键菜单的方式进行功能的展示,如下界面所示. 这种方式是我们常规的界面生成和布局方式,对于功能相对较少的业务模块来说,是比较简洁的,多数操作都放在了右键

在Winform框架界面中改变并存储界面皮肤样式

在本篇介绍的Winform界面样式改变及存储操作中,是指基于DevExpress进行界面样式的变化.一般情况下,默认我们会为客户提供多种DevExpress的界面皮肤以供个人喜好选择,默认DevExpress提供40余种皮肤样式,用户可以根据自己的喜好,选择较为美观.得体的皮肤,为了方便,我们对用户的皮肤选择进行记录,并可以动态改变. 1.界面皮肤的选择 Winform开发框架(包括混合式Winform开发框架)皮肤如下界面所示. 在皮肤集合中打开,可以看到很多界面皮肤可供选择 上面初始化的皮肤

在Winform界面菜单中实现动态增加【最近使用的文件】菜单项

在我们一些和文件处理打交道的系统中,我们往往需要记录下最近使用的文件,这样方便用户快速打开之前浏览或者编辑过的文件,这种在很多软件上很常见,本文主要介绍在Winform界面菜单中实现[最近使用的文件]动态菜单的处理,实现一个较为常用的功能. 在我上篇随笔<文字处理控件TX Text Control的使用>介绍的内容中,我针对性的对这个控件的使用做了一个全面的了解,发现其中案例代码总这部分的功能实现[最近使用的文件]挺好,于是把它进行了整理,把整个思路作为一篇随笔进行记录,希望对大家有所帮助.