WinForm应用实战开发指南 - 如何用自定义控件丰富界面效果处理?

WinForm应用实战开发指南 - 如何用自定义控件丰富界面效果处理? Winform界面开发部分往往也用到了自定义的用户控件对应一些特殊的界面或者常用到的一些局部界面内容我们可以使用自定义的用户控件来提高界面的统一性同时也增强了使用的便利性。如我们Winform界面中用到的分页控件、附件显示内容、以及一些公司、部门、菜单的下拉框列表等等由于重复多处使用因此一处封装多处收益。PS给大家推荐一个C#开发可以用到的界面组件——DevExpress WinForms它能完美构建流畅、美观且易于使用的应用程序无论是Office风格的界面还是分析处理大批量的业务数据它都能轻松胜任DevExpress新旧版本帮助文档获取可点击这篇文章查看——《界面控件DevExpress v26.1帮助文档大全CHM版本》回顾Winform界面中自定义的用户控件处理场景之前介绍了不少的控件使用、以及自定义控件的使用例子如模仿牙医管家的软件界面的部分来创建一些自定义部分的内容。根据其中显示的内容部分制作了一个用户控件在其中添加一个LayoutControl方便控制布局添加一些标签以及设置了一些图标得到下图所示。其中定义的用户控件的源码部分继承自XtraUserControl用户控件基类如果是传统样式的Winform界面可以继承自UserControl修改其中源码增加对应的属性方便动态设置用户控件的相关属性如颜色块、项目背景色以及绑定的对象信息等内容。然后通过自定义控件的事件或者方法对界面内容进行更新处理即可完成后我们看界面的效果如下所示较为符合实际的效果即可。一般来说一个窗体用户控件不多的情况下Winform界面的效果还是挺好的如果界面的用户控件很多如超过几千个那么可能会有性能问题。动态展现大量历史号码信息的自定义控件的时候就会出现一些句柄创建错误的问题。控件集合可以通过布局TableLayoutPanel表格布局或者FlowLayoutPanel顺序流布局来添加即可如果利用TableLayoutPanel来展示那么需要设置好每列的宽度或者比例如下界面所示。表格的行列定义如下所示。由于自定义控件我们需要跟踪用户的单击处理并且需要把这个逻辑逐步推动到顶级界面上去进行处理因此需要定义一个事件信息如下所示。/// summary /// 事件处理 /// /summary public EventHandlerClickEventData ClickEventHandler { get; set; }控件的动态添加处理可以同时指定它的匿名事件的处理逻辑从而对控件的事件进行更新。var controlList new ListLotteryItemControl2(); foreach (var info in list) { var control new LotteryItemControl2(); control.Qi info.LineNo.ToString(D2); var numberList new Liststring() { info.No1.ToString(D2), info.No2.ToString(D2), info.No3.ToString(D2), info.No4.ToString(D2), info.No5.ToString(D2), info.No6.ToString(D2), info.No7.ToString(D2), }; control.NumberList numberList; control.BindData(); control.ClickEventHandler (s, data) { //遍历所有的控件统一处理样式 foreach (var subCtrl in panel.Controls) { if (subCtrl is LotteryItemControl2 lottery) { lottery.SetSelected(data); } } }; controlList.Add(control); } this.panel.Controls.AddRange(controlList.ToArray());如果我们不喜欢每个控件都对事件进行一个层层的处理也可以引入MediatR来实现事件总线的处理。我们在程序启动的时候注入对应的接口服务IMediator那么就可以通过该静态类的 GetService方法获取对应的注入接口IMediator我们需要利用该接口来发送Send请求/应答命令或者发布Publish消息的处理。public partial class TestMediatR : BaseForm { private readonly IMediator _mediator; public TestMediatR() { InitializeComponent(); _mediator ServiceLocator.GetServiceIMediator(); }MediatR是一个跨平台通过一种进程内消息传递机制进行请求/响应、命令、查询、通知和事件的消息传递并通过C#泛型来支持消息的智能调度其目的是消息发送和消息处理的解耦。它支持以单播和多播形式使用同步或异步的模式来发布消息创建和侦听事件。它主要的几个对象IMediator主要提供Send与Publish方法需要执行的命令都是通过这两个方法实现IRequest、IRequest命令查询 | 处理类所继承的接口一个有返回类型一个无返回类型一个查询对应一个处理类程序集只认第一个扫描到的类。IRequestHandler实现Handle方法 命令处理接口。命令查询 | 处理类继承它也可以继承AsyncRequestHandler实现抽象Handle方法、RequestHandler实现抽象Handle方法接口INotification命令查询 | 处理类所继承的接口这个没有返回与IRequest不通的是可以对于多个处理类INotificationHandler与IRequestHandler一样的只不过这是INotification的处理接口例如我们发送消息后收到应答消息结果展示在界面中的如下所示。/// summary /// 使用请求、应答的消息进行测试获得返回结果后输出显示 /// /summary private async void btnSend_Click(object sender, EventArgs e) { //应答处理 var outputMessage await _mediator.Send(new RetrieveInfoCommandRequest { Text this.txtSend.Text }); Console.WriteLine(outputMessage.OutputMessage); this.txtReceived.AppendText(outputMessage.OutputMessage Environment.NewLine); }如果控件比较多处理的时候刷新的时候记得移除面板上已经添加的控件。//清空界面 while (panel.Controls.Count 0) { var controltoremove panel.Controls[0]; panel.Controls.RemoveAt(0); controltoremove.Dispose(); } panel.Controls.Clear();Winform界面中自定义的用户控件处理例如在附件管理的时候对于一些窗体的信息我们需要了解该业务对应的附件信息有几个并且提供入口可以查看或者管理附件列表那么可以根据需要封装一个自定义附件管理的自定义用户控件。在实际界面应用的时候由于附件管理的自定义控件已经封装好了所以在使用的时候拖动到界面即可如下界面所示。我们在做病历管理的时候就需要大量用到不同的分类的附件信息的展示如下界面效果所示。还有就是有时候对于权限管理里面部门信息在不少的地方用到如果每次对原始的下拉列表处理那么增加不少工作量如果把它封装为自定义控件和常规的控件一样使用即可就会很方便如下界面所示。它的实际展示效果如下所示。单击下拉列表后展示部门的列表信息。同理用户控件一旦创建后我们可以在很多需要的地方直接使用省却初始化的一些代码操作。我们在初始化的时候显示相关的部门列表选择后获得部门的ID也可以设置部门的ID。/// summary /// 部门显示控件 /// /summary public partial class DeptControl : XtraUserControl { public string ParentOuID -1; /// summary /// 选择的值发生变化的时候 /// /summary public event EventHandler EditValueChanged; public DeptControl() { InitializeComponent(); this.txtDept.EditValueChanged new EventHandler(cmbUpperOU_EditValueChanged); } void cmbUpperOU_EditValueChanged(object sender, EventArgs e) { if (EditValueChanged ! null) { EditValueChanged(sender, e); } } private async void DeptControl_Load(object sender, EventArgs e) { if (!this.DesignMode) { //限定用户的选择级别 var list await Portal.gc.GetMyTopGroup(); foreach (OuInfo OuInfo in list) { if (OuInfo ! null) { this.ParentOuID OuInfo.Id.ToString(); } } Init(); } }需要可以响应相关的编辑事件用来触发关联的信息变化如下所示是自定义控件的使用代码。public partial class FrmEditUser : BaseEditForm { public FrmEditUser() { InitializeComponent(); this.txtDept.EditValueChanged new EventHandler(txtDept_EditValueChanged); } void txtDept_EditValueChanged(object sender, EventArgs e) { if (!string.IsNullOrEmpty(txtDept.Value)) { InitManagers(txtDept.Value.ToInt32()); } }在介绍一个场景我们在一些选择用户的界面中如CRM中对于分配用户、工作流中选择流程用户的操作中往往需要选择系统的人员列表可以多个选择那么我们可以设计界面如下所示。其中选择的人员用红色方框标识这个部分的用户和移除图标是自定义控件界面如下所示。主要就是方便对用户进行显示和移除设置的一些简单的封装。在比如在工作流的创建入口中我们展示相关可以创建流程的快速入口通过一些图片、文字来展示工作流程的信息单击事件进行弹出不同的流程对话框处理过程。这个过程主要就是美观性的要求是相对于全部文本信息的单调有一些改善的效果。本文转载自博客园 - 伍华聪