在一个给客户做的项目中,界面要求修改增加通用工具栏按钮的事件处理,也就是在主界面中放置几个固定的功能操作按钮,打开不同的页面的时候,实现对应页面的功能处理,这种和我标准的界面处理方式有所不同,标准的列表界面,一般在界面中放置了一些常规的按钮,如查询/更新、新建、编辑、删除、导入、导出等常规操作,现在是需要把这些提升到主界面的层次上放置按钮,这种处理方式也算是提供一种方便吧。本篇随笔介绍实现这个功能的思路和代码实现逻辑。
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接口,然后调用对应的处理函数实现功能的绑定。
这篇就是我对于实现这种通用按钮事件处理的思路和具体逻辑代码,供大家参考学习,有错漏之处还请多多包涵。
我已经实现了最新的appcompat库,并使用工具栏作为操作栏。但问题是我无法捕捉主页按钮/汉堡包图标点击事件。我试过了,看了所有的东西,但似乎没有发现类似的问题。 这是我的类: 这是我的NavigationDrawerFrament类: 当我单击菜单项时,会调用日志“item selected”。但当我点击home按钮时,它会打开导航抽屉,但从未调用“home selected”日志。我也在我的
本文向大家介绍java处理按钮点击事件的方法,包括了java处理按钮点击事件的方法的使用技巧和注意事项,需要的朋友参考一下 不同的事件源可以产生不同类别的事件。例如,按钮可以发送一个ActionEvent对象,而窗口可以发送WindowEvent对象。 AWT时间处理机制的概要: 1. 监听器对象是一个实现了特定监听器接口(listener interface)的类的实例。 2. 事件源是一个能够
在此对话框您可以指定当浏览磁盘文件夹 (“在压缩文件外部时显示”选项) 或查看压缩文件内容 (“在压缩文件内部时显示”选项 ) 时,要显示哪一些工具栏按钮。可以改变按钮的顺序,只要选择您希望移动的按钮并按下“上移”或“下移”来改变它们的位置。如果您要恢复默认工具栏配置,按下“默认”按钮。 “分隔符”按钮在选择的当前按钮前插入一个分隔符线。如果您要移除一个分隔符,或者取消它的选择状态,或者再次按下“
本文向大家介绍winform实现关闭按钮失效的两种方法,包括了winform实现关闭按钮失效的两种方法的使用技巧和注意事项,需要的朋友参考一下 本文实例讲述了winform实现关闭按钮失效的两种方法。分享给大家供大家参考。具体如下: 第一种: 这种方法让窗体的关闭按钮还是存在的,但是,鼠标操作关闭按钮是没有效果的。这种一般在系统利用第三方控件后,出现别的方法使禁用关闭按钮失效,但是,这种方法可以确
本文向大家介绍详解iOS中按钮点击事件处理方式,包括了详解iOS中按钮点击事件处理方式的使用技巧和注意事项,需要的朋友参考一下 写在前面 在iOS开发中,时常会用到按钮,通过按钮的点击来完成界面的跳转等功能。按钮事件的实现方式有多种,其中较为常用的是目标-动作对模式。但这种方式使得view与controller之间的耦合程度较高,不推荐使用; 另一种方式是代理方式,按钮的事件在view中绑定,co
我有一个有几个按钮的工具栏。我想要几个按钮来加载不同的FXML文件。现在的方法是用Java代码编写fxml文件,并在每次调用时插入它。如果我可以调用FXML文件并获得正确的场景,这将是一个更好的选择。这是我加载设置视图的示例: 我以前使用过tabpane,它的便利之处在于它可以加载“内容”,在某种程度上,它是一个actionlistener,可以加载fxml文件。我希望工具栏按钮具有此功能。 我们