没有找到合适的产品?
联系客服协助选型:023-68661681
提供3000多款全球软件/控件产品
针对软件研发的各个阶段提供专业培训与技术咨询
根据客户需求提供定制化的软件开发服务
全球知名设计软件,显著提升设计质量
打造以经营为中心,实现生产过程透明化管理
帮助企业合理产能分配,提高资源利用率
快速打造数字化生产线,实现全流程追溯
生产过程精准追溯,满足企业合规要求
以六西格玛为理论基础,实现产品质量全数字化管理
通过大屏电子看板,实现车间透明化管理
对设备进行全生命周期管理,提高设备综合利用率
实现设备数据的实时采集与监控
利用数字化技术提升油气勘探的效率和成功率
钻井计划优化、实时监控和风险评估
提供业务洞察与决策支持实现数据驱动决策
原创|使用教程|编辑:龚雪|2020-10-23 10:26:06.567|阅读 499 次
概述:本文将为大家介绍在WinForm界面开发时,如何实现通用工具栏按钮的事件处理。evExpress WinForm v20.1.8全新发布,欢迎下载体验新功能!
# 界面/图表报表/文档/IDE等千款热门软控件火热销售中 >>
相关链接:
DevExpress Winforms Controls 内置140多个UI控件和库,完美构建流畅、美观且易于使用的应用程序。DevExpress WinForm v20.1全新发布,想要体验?点击下载>>
在一个给客户做的项目中,界面要求修改增加通用工具栏按钮的事件处理,也就是在主界面中放置几个固定的功能操作按钮,打开不同的页面的时候,实现对应页面的功能处理,这种和标准的界面处理方式有所不同,标准的列表界面,一般在界面中放置了一些常规的按钮,如查询/更新、新建、编辑、删除、导入、导出等常规操作,现在是需要把这些提升到主界面的层次上放置按钮,这种处理方式也算是提供一种方便吧。本文将为大家介绍实现这个功能的思路和代码实现逻辑。
这里要实现的通用工具栏按钮的事件处理,具体的界面是这样的,我们处于一个多文档的主界面中,在主界面的顶部工具栏放置这些通用的工具栏按钮,以便提高相关的处理便利和效率。
从上面的界面我们可以看到,程序主界面的顶部工具栏上有一些常规的操作,包括如查询、新建、编辑、删除、导入、导出等按钮,可以为程序的功能操作提供方便。
当我们打开一个新的窗体页面,那么对应的按钮事件也应该和这个窗体相关,或者我们切换到其他窗体,那么按钮的处理事件也应该跟着变化到对应的窗体上,这种就是我们需要的效果。
上面的逻辑也就是我们新建一个窗体、或者切换一个窗体,那么需要通知顶部工具栏进行更新或者进行一个对接的处理才可以。
由于我们想尽可能的减少开发的工作量,因此希望在基类进行一些事件或者接口的封装,以便降低新建列表窗体的时候的代码编写。
对于一个如查询操作的处理事件,我们需要定义一个接口来实现这个功能,这样我们才可以在打开的窗体的时候,把它转换为对应的接口处理。
例如我们定义一个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
通过基类的这样处理,我们就可以在具体列表窗体里,赋值给对应的事件就可以了。
例如我们处理一个应用菜单的列表管理界面,定义窗体如下所示,继承了我们所实现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);};
}
这样我们就知道对应接口是如何和具体的页面事件发生关系了。
我们在构建主界面的左侧功能树的时候,我们通过树列表的选中事件加载对应的窗体,具体代码如下所示。
//处理树形菜单的点击操作,如果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接口,然后调用对应的处理函数实现功能的绑定。
以上就是我对于实现这种通用按钮事件处理的思路和具体逻辑代码,供大家参考学习,有错漏之处还请多多包涵。
本文转载自
DevExpress技术交流群2:775869749 欢迎一起进群讨论
富文本控件难上手?这堂公开课你一定不能错过,不同视图不同应用场景全解!
本站文章除注明转载外,均为本站原创或翻译。欢迎任何形式的转载,但请务必注明出处、不得修改原文相关链接,如果存在内容上的异议请邮件反馈至chenjj@ke049m.cn
文章转载自:



大型SaaS系统的自动化测试常常受制于界面变化快、结构复杂、加载机制多变等因素。从元素识别到脚本管理,SmartBear TestComplete帮助Salesforce建了可靠的自动化测试体系。
BarTender 标签管理系统,正是帮助企业轻松实现 GS1 标准化标签设计、编码生成与信息联动的强大工具。
Parasoft C/C++test 是一款功能强大的 C/C++ 软件测试工具,集成了静态代码分析、单元测试、集成测试和覆盖率分析等功能,单元测试作为其关键功能之一,为了适配多样化的目标部署环境,C/C++test 设计了灵活的测试结果收集机制。通过Socket通讯方式来收集单元测试结果,从而扩展其测试覆盖范围与应用场景。
Parasoft C/C++test作为一款功能全面的自动化代码质量保障工具,为C/C++开发者提供了静态分析、单元测试和运行时错误检测等核心功能。通过将其与轻量级且广受欢迎的VScode编辑器集成,开发团队可以在熟悉的编码环境中实时获得代码质量反馈,有效提升开发效率与代码可靠性。
相关产品
优秀的界面控件开发包,帮助企业构建卓越应用!
DevExpress DXperience Subscription高性价比的企业级.NET用户界面套包,助力企业创建卓越应用!
DevExpress WinForms Subscription为Windows Forms平台创建具有影响力的业务解决方案,高性价比WinForms界面控件套包。
最新文章 MORE
半岛外围网上直营相关的文章 MORE
服务电话
重庆/ 023-68661681
华东/ 13452821722
华南/ 18100878085
华北/ 17347785263
客户支持
技术支持咨询服务
服务热线:400-700-1020
邮箱:sales@ke049m.cn
关注我们
地址 : 重庆市九龙坡区火炬大道69号6幢
半岛外围网上直营 