在Winform界面使用自定义用户控件及TabelPanel和StackPanel布局控件

在很多时候,我们做一些非常规化的界面的时候,往往需要创建一些用户控件,在其中绘制好一些基础的界面块,作为后续重复使用的一个单元,用户控件同时也可以封装处理一些简单的逻辑。在开发Winform各种类型项目,我都时不时需要定制一些特殊的用户控件,以方便在界面模块中反复使用。我们一般是在自定义的用户控件里面,添加各种各样的界面控件元素,或者封装一些特殊的函数处理共外部调用等。本篇随笔主要介绍基于DevExpress的Winform开发经验,介绍一个类似看板信息的用户控件,并在TabelLayout和StackLayout布局控件中进行展示。

1、用户控件界面的处理

在偶尔的一个场合下,看到一个牙医管家的软件界面做的非常不错,其中有一个预约列表的界面感觉非常好,如下界面所示。

其中它的每个用户信息列表里面,都是一个综合信息的展示,非常直观,估计应该是用户自定义控件做的。

在其中里面,有不同的字体,各式图标,以及内容的信息展示, 这个我在DevExpress的列表控件里面,没有看到可以如此定义列表内容的,在DevExpress的GridView里面有一个看板模板的定义有点接近,但是试了一下,可调性不好,于是放弃寻求其他接近方案,玩遍DevExpress的控件后,发现最好的方式应该是自定义用户控件的方式来解决这个界面问题。

花了一点时间,制作了一个用户控件,在其中添加一个LayoutControl方便控制布局,添加一些标签以及设置了一些图标,得到下图所示。

左侧的颜色条由于使用Group控件,因此宽度暂时无法调整,如果介意大小,我们可以在其中在创建一个LayoutControl,然后在其中方式内容即可。

我们改变布局,然后添加一个颜色块,得到类似界面如下所示。

我们来定义一下用户控件的源码部分,修改其中源码,增加对应的属性,方便动态设置用户控件的相关属性,如颜色块,项目背景色,以及绑定的对象信息等内容。

然后在界面加载完毕后,设置对应的信息和颜色信息,如下代码所示。

        /// <summary>
        /// 窗口加载事件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void UserItemControl_Load(object sender, EventArgs e)
        {
            BindData();
            RefreshColor();
        }

        /// <summary>
        /// 根据用户定义信息,显示不同的内容
        /// </summary>
        private void BindData()
        {
            if(this.UserItemInfo != null)
            {
                var info = this.UserItemInfo;
                this.lblCustomerName.Text = info.CustomerName;
                this.lblMobile.Text = info.Mobile;
                this.lblReceiver.Text = info.Receiver;
                this.lblRecordDate.Text = info.RecordDate;
                this.lblRecordNo.Text = info.RecordNo;
                this.lblDealType.Text = "";
                this.lblStar.ImageOptions.ImageIndex = GetStarImageIndex(info.Stars);
                if (!info.IsVip)
                {
                    this.lblVip.Visibility = LayoutVisibility.Never;
                }
            }
        }

        /// <summary>
        /// 刷新背景色
        /// </summary>
        private void RefreshColor()
        {
            if (ItemBlockColor != Color.Empty)
            {
                this.itemColor.AppearanceItemCaption.BackColor = ItemBlockColor;
            }
            if (ItemBackColor != Color.Empty)
            {
                layoutControl1.BackColor = ItemBackColor;
            }
        }

但我们鼠标浮动在项目上或者离开的时候,或者单击某项的时候,我们变换下颜色,方便区分显示。

        private void layoutControl1_MouseLeave(object sender, EventArgs e)
        {
            if (!this.IsSelected)
            {
                this.layoutControl1.ResetBackColor();
            }
        }

        private void layoutControl1_MouseEnter(object sender, EventArgs e)
        {
            if (!this.IsSelected)
                this.layoutControl1.BackColor = Color.FromArgb(192, 255, 192);
        }

        private void layoutControl1_Click(object sender, EventArgs e)
        {
            this.IsSelected = true;
            OnItemClick?.Invoke(this, e);
        }

完成这些后,我们需要在窗体上对内容进行初始化。

最后我们看看界面的效果如下所示

或者下面这样的界面布局。

如果嫌弃边框红色不好看,我们 可以修改边框为灰色调一点的,这样总体看起来效果如下所示。

得到和我们最终需要的界面很接近了。

一般除了悬浮鼠标颜色变化外,控件单击后,我们会设置不同的背景色,以示区分。

        /// <summary>
        /// 是否选中节点
        /// </summary>
        public bool IsSelected
        {
            get
            {
                return m_IsSelected;
            }
            set
            {
                m_IsSelected = value;

                this.ItemBackColor = value ? Color.FromArgb(255, 255, 192) : Color.Transparent;
                this.RefreshColor();
            }
        }

一般列表界面中,我们除了支持鼠标移动、单击变色的效果外,我们还希望支持通过键盘箭头上下键进行上下浏览项目。我们如果需要使用键盘的按键,需要设置窗体的KeyPreview属性为True,

然后跟踪按键的事件即可,如下所示。

            this.KeyPreview = true;
            this.KeyUp += FrmKanBan_KeyUp;

按键事件捕捉处理如下所示,主要就是判断选中的用户控件,并对面板的子控件的选中效果进行处理。

        private void FrmKanBan_KeyUp(object sender, KeyEventArgs e)
        {
            //单击鼠标或者切换按键,会触发用户控件获得selectItem对象,可以进行箭头上下移动
            if (selectItem != null)
            {
                var panel = selectItem.Parent;
                if (panel != null)
                {
                    //获取操作项的索引值
                    int oldIndex = panel.Controls.IndexOf(selectItem);
                    if (e.KeyCode == Keys.Up)
                    {
                        if (oldIndex > 0)
                        {
                            //通过序号获得新的控件,并单击它触发选择事件
                            var newCtrl = panel.Controls[oldIndex - 1];
                            Item_OnItemClick(newCtrl, new EventArgs());
                        }
                    }
                    else if (e.KeyCode == Keys.Down)
                    {
                        if (oldIndex < (panel.Controls.Count - 1))
                        {
                            //通过序号获得新的控件,并单击它触发选择事件
                            var newCtrl = panel.Controls[oldIndex + 1];
                            Item_OnItemClick(newCtrl, new EventArgs());
                        }
                    }
                }
            }
        }

界面中用户控件的切换选中效果,需要先清空之前所有的选择,然后在设置新的选中控件,所以还需要对控件触发单击事件进行处理,如下所示。

        /// <summary>
        /// 选中的用户控件对象实例
        /// </summary>
        UserItemControl selectItem = null;
        /// <summary>
        /// 单击用户控件,触发清除所有标记后,再次设置选中的项目标记
        /// </summary>
        private void Item_OnItemClick(object sender, EventArgs e)
        {
            //清空所有控件的选中标记
            var panel = (PanelControl)((Control)sender).Parent;
            foreach (Control ctrl in panel.Controls)
            {
                var item = ctrl as UserItemControl;
                if(item != null)
                {
                    item.IsSelected = false;
                }
            }

            //设置选中控件
            selectItem = ((UserItemControl)sender);
            selectItem.IsSelected = true;
            this.Text = selectItem.UserItemInfo.CustomerName + "-选中";

            //如果在面板中遮挡,移动滚动条,可以查看到完整用户控件界面
            panel.ScrollControlIntoView(selectItem);
        }

如下效果所示。

2、TabelLayout和StackLayout布局控件的介绍和使用

我们在做Winform开发的时候,一般知道,微软传统Winform的布局提供两个控件,FlowLayoutPanel和TableLayoutPanel,一个是流式布局,一个是表格布局,各有各的用处。流式布局主要就是按照顺序挨个放置控件,表格布局主要按照表格的定义的行列单元格,严格放置控件,表格单元格控制强度更大,而且控件具有拉伸效果。

对于DevExpress,我们一般还是倾向于采用它提供给的控件来做界面,可以很好融合它的皮肤效果,相对于Winform传统两个布局控件,DevExpress提供了两个封装效果相当的控件布局StackPanel和 TablePanel,他们的效果实现大同效果,不过调用的接口不同。

对于两个控件,我们希望里面的内容自动出现滚动条,那么设置属性AutoScroll 为True即可,如下代码所示。

panel.AutoScroll = true;

而StackPanel另外需要LayoutDirection,也就是控件顺序展现的方式,如下代码所示。

panel.LayoutDirection = StackPanelLayoutDirection.TopDown;

使用StackPanel面板来测试展示用户控件列表的界面代码如下所示。

        /// <summary>
        /// 使用StackPanel对用户控件布局进行处理
        /// </summary>
        private void InitPanel(StackPanel panel)
        {
            panel.AutoScroll = true;//面板自动出现滚动条
            panel.LayoutDirection = StackPanelLayoutDirection.TopDown;//从上往下展示
            panel.Controls.Clear();//清空界面

            var list = GetInfoList(); //获取用户控件绑定的对象信息列表
            for (int i = 0; i < list.Count; i++)
            {
                //定义用户控件实例
                var item = new UserItemControl();
                item.UserItemInfo = list[i];//绑定对象信息

                item.Anchor = AnchorStyles.Top | AnchorStyles.Left | AnchorStyles.Right;
                item.ItemBlockColor = colors[i %10]; //变化颜色
                item.OnItemClick += Item_OnItemClick;//触发选中事件

                panel.Controls.Add(item);
            }
        }

对于表格布局TablePanel控件来说,使用初始化控件的方式也差不多,不过有个别地方注意即可。

        /// <summary>
        /// 使用TablePanel对用户控件布局进行处理
        /// </summary>
        private void InitPanel(TablePanel panel)
        {
            panel.AutoScroll = true;//面板自动出现滚动条
            panel.Controls.Clear();//清空界面
            panel.Rows.Clear();//清空行
            panel.Columns.Clear();//清空列

            //添加列定义(增加一个列即可)
            panel.Columns.Add(new TablePanelColumn(TablePanelEntityStyle.Relative, 55F));
            var list = GetInfoList(); //获取用户控件绑定的对象信息列表
            for (int i = 0; i < list.Count; i++)
            {
                //定义行信息
                panel.Rows.Add(new TablePanelRow(TablePanelEntityStyle.AutoSize, 100F));

                //定义用户控件实例
                var item = new UserItemControl();
                item.UserItemInfo = list[i];
                //定义拉伸效果
                item.Anchor = AnchorStyles.Top | AnchorStyles.Left | AnchorStyles.Right;
                item.ItemBlockColor = colors[i % 10]; //变化颜色
                item.OnItemClick += Item_OnItemClick;//触发选中事件

                //先添加控件到面板集合中
                panel.Controls.Add(item);
                //设置控件的单元格位置
                panel.SetCell(item, i, 0);
            }

            //添加多一行,确保布局
            panel.Rows.Add(new TablePanelRow(TablePanelEntityStyle.AutoSize, 100F));
        }

添加控件的时候,需要注意下面的代码,才能正常展示控件信息,否则无法看到用户控件。

                //先添加控件到面板集合中
                panel.Controls.Add(item);
                //设置控件的单元格位置
                panel.SetCell(item, i, 0);

最后对比下效果,左边是TablePanel,右边是StackPanel展现出来的效果。

以上就是界面如何在DevExpress开发中使用各种用户控件进行用户控件的创建、以及实现鼠标进入、移出、单击的不同效果,以及实现键盘上下箭头按键的事件选中效果,并介绍DevExpress中两个布局控件TabelPanel和StackPanel的正常使用,达到展示控件信息的作用。

原文地址:https://www.cnblogs.com/wuhuacong/p/12201665.html

时间: 2025-01-01 07:13:57

在Winform界面使用自定义用户控件及TabelPanel和StackPanel布局控件的相关文章

ExtJs4 笔记(9) Ext.Panel 面板控件、 Ext.window.Window 窗口控件、 Ext.container.Viewport 布局控件 (转 )出处:[Lipan] (http://www.cnblogs.com/lipan/)

本篇讲解三个容器类控件. 一.面板控件 Ext.Panel 一个面板控件包括几个部分,有标题栏.工具栏.正文.按钮区.标题栏位于最上面,工具栏可以在四个位置放置,围绕中间部分正文,按钮区位于最小方.下面介绍几个基本配置项: 1.title:设置面板标题文本. 2.tbar,lbar,rbar,bbar:分别设置上.左.右.下四个部位的工具栏. 3.html,items:前者用来设置正文部分的html,后者设置正文部分的ext控件. 4.buttons:设置按钮区的按钮. 下面看看面板生成代码:

WinForm界面开发之布局控件&quot;WeifenLuo.WinFormsUI.Docking&quot;的使用

http://www.cnblogs.com/wuhuacong/archive/2009/07/09/1520082.html 本篇介绍Winform程序开发中的布局界面的设计,介绍如何在我的共享软件中使用布局控件"WeifenLuo.WinFormsUI.Docking". 布局控件"WeifenLuo.WinFormsUI.Docking"是一个非常棒的开源控件,用过的人都深有体会,该控件之强大.美观.不亚于商业控件.而且控件使用也是比较简单的.先看看控件使用

winform界面开发-HTML内容编辑控件

参照及推荐博客:伍华聪 http://www.cnblogs.com/wuhuacong/archive/2009/07/07/1518346.html http://www.cnblogs.com/wuhuacong/p/3560685.html 这篇文章介绍了作者软件的开发及成长历程,作者在十几年的开发历程中注重思考.总结.归纳和整理,形成了自己的开发风格,其中很多经验之处值得我们借鉴和学习,至少使我提前意识到软件开发成长历程中除了技术的熟练程度之外更应该注重的是开发思想.开发心得及开发思路

布局控件的概述

今日看博客园的Kevin Fan的博客,受益不少,把相关的内容精简出来,以方便 自已以后浏览. 附上kevin Fan 的博客地址:http://www.cnblogs.com/jv9/archive/2010/04/11/1709527.html. 开发windows phone 应用,免不了需要使用各种控件,kevin Fan 概括了三种类型的控件,之前自已一直没留意这方面的详细分类,看了他的分类后,作了纪录,以方便自已和他人. 界面控件,主要分为布局控件.项目控件.用户交互控件,下面主要纪

背水一战 Windows 10 (54) - 控件(集合类): ItemsControl 的布局控件 - OrientedVirtualizingPanel, VirtualizingStackPanel, WrapGrid

[源码下载] 作者:webabcd 介绍背水一战 Windows 10 之 控件(集合类 - ItemsControl 的布局控件) OrientedVirtualizingPanel VirtualizingStackPanel WrapGrid 示例1.OrientedVirtualizingPanel(基类) 的示例Controls/CollectionControl/ItemsControlDemo/LayoutControl/OrientedVirtualizingPanelDemo.

背水一战 Windows 10 (53) - 控件(集合类): ItemsControl 的布局控件 - ItemsStackPanel, ItemsWrapGrid

[源码下载] 作者:webabcd 介绍背水一战 Windows 10 之 控件(集合类 - ItemsControl 的布局控件) ItemsStackPanel ItemsWrapGrid 示例1.ItemsStackPanel 的示例Controls/CollectionControl/ItemsControlDemo/LayoutControl/ItemsStackPanelDemo.xaml <Page x:Class="Windows10.Controls.Collection

WinForm界面布局控件WeifenLuo.WinFormsUI.Docking&quot;的使用 (一)

WinForm界面布局控件WeifenLuo.WinFormsUI.Docking"的使用 (一) 编写人:CC阿爸 2015-1-28 在伍华聪的博客中,看到布局控件"WeifenLuo.WinFormsUI.Docking",发现的确是一个非常棒的开源控件,用过的人都深有体会,该控件之强大.美观.不亚于商业控件.而且控件使用也是比较简单的今天在这里,我想与大家一起分这一伟大的控件.有兴趣的同学,可以一同探讨与学习一下,否则就略过吧. 一.引用方法: 1.建立一个WinFo

Android自定义用户控件简单范例(一)

一款优秀的移动应用需要具有自己独特统一的风格,通常情况下UI设计师会根据产品需求和使用人群的特点,设计整体的风格,界面的元素和控件的互效果.而原生态的Android控件为开发人员提供的是最基本的积木元素,如果要准确地传递统一的视觉效果和交互体验,对控件的自定义使用是非常有必要的. 这篇文章通过一个简单的从Java后台程序中进行创建的示例来说明Android自定义控件的运行原理. <LinearLayout xmlns:android="http://schemas.android.com/

Android自定义用户控件简单范例(二)

对于完全由后台定制的控件,并不是很方便其他人的使用,因为我们常常需要看到控件放到xml界面上的效果,并根据效果进行布局的调整,这就需要一个更加标准的控件制作流程: 我们的自定义控件和其他的控件一样,应该写成一个类,而这个类的属性是是有自己来决定的. 我们要在res/values目录下建立一个attrs.xml的文件,并在此文件中增加对控件的属性的定义. 使用AttributeSet来完成控件类的构造函数,并在构造函数中将自定义控件类中变量与attrs.xml中的属性连接起来. 在自定义控件类中使