效果:

描述:

这是一个可折叠的菜单导航,主要是由panel、picturebox、label完成,界面的颜色用来区分一下各个组合控件,便于调试。
首先,首先是ImageButton:
这个是由PictureBox和Label构成。
1.文字部分的居中需要设置label的宽度为父容器的宽度。
2.图片设置 picBox.SizeMode = PictureBoxSizeMode.StretchImage
 
然后是单个的菜单 命名为:ButtonGroup:
顶部灰色的是一个label,绿色里面的是一个包含ImageButton的列表。
1.顶部这个label注册了一个click事件,是为了完成点击它的时候会展开。
 
最后是整个的菜单,就是由ButtonGroup组成的一个list,我给它命名为:CustomNavBar。
 
这里需要注意的是:
事件的封装,像这种自定义控件,都是要定义自定义事件,并且把它暴露出来,元控件触发的时候,才触发这个暴露出来的控件。代码类似这种:
private void PicBoxClick(object sender,EventArgs args)
{
PictureBoxClick?.Invoke(sender, this.text);
}
PicBoxClick是PictureBox控件的原生Click事件,PictureBoxClick是我们自己定义的事件,这个事件需要到控件外部注册,就像这样:
for (int i = 0; i < _listImageButton.Count; i++)
{
var imgButton = _listImageButton[i];
 
imgButton.Top = i * imgButton.Height;
imgButton.Left = 0;
 
imgButton.PictureBoxClick += ImgButton_PictureBoxClick;
 
ButtonArea.Controls.Add(imgButton);
}
这段代码中,_listImageButton是属于ButtonGroup控件里的集合,这样做,最终点击PictureBox的时候,其实是调用ImgButton_PictureBoxClick这个方法里的内容。
假如这个ButtonGroup已经是最外层的自定义控件了,那么这个ImgButton_PictureBoxClick就属于供这个完整的自定义控件使用人也就是客户自己自定义的事件了,这个里面的代码就可以根据不同的客户,内容就可以不同了。
因为这个控件最外层的自定义控件是CustomNavBar,所以在CustomNavbar里还自定义了一个相同委托的事件:
public delegate void ImageButtonClick(object o,string moduleName);
public event ImageButtonClick NavButtonClick;
 
 
这代码也是我从其他地方下载的,然后自己看了一篇,在自己敲的。敲的过程中,了解到了内部类的使用,最大的收获是:一般窗体都是要有partial修饰的,而InitializeComponent()方法都是放在自动生成的代码里的,做这个控件的时候,我还是自己第一次这样通过写代码的方式来初始化一个控件。

代码:

public partial class CustomNavBar : UserControl
{
public CustomNavBar()
{
InitializeComponent();
InitializeButtonGroup();
pnlMain.BackColor = Color.DarkOliveGreen;
ResetMenu();
}
private string _jsonString;
/// <summary>
///暴露接口,可从外部(数据库)获得菜单的信息
/// </summary>
public string JsonString
{
get { return _jsonString; }
set { _jsonString = value; }
} private List<ButtonGroup> listGroup;
private int currentItemIndex; public delegate void ImageButtonClick(object o,string moduleName); public event ImageButtonClick NavButtonClick; public void InitializeButtonGroup()
{
listGroup = new List<ButtonGroup>() {
new ButtonGroup("欢迎使用",
new List<ImageButton>()
{
new ImageButton("欢迎使用",Resources.LogoMain),
new ImageButton("员工信息管理",Resources.LogoManageEmployee)
}), new ButtonGroup("系统设置",
new List<ImageButton>(){
new ImageButton("部门管理", Resources.LogoManageDepartment)}), new ButtonGroup("退出系统",null)
};
ButtonGroup bgPre=null;
int sum = ;
for (int i = ; i < listGroup.Count; i++)
{
int height = bgPre == null ? : bgPre.Height;
sum += height;
var buttonGroup = listGroup[i]; buttonGroup.Tag = i; buttonGroup.SetButtonLocation(); buttonGroup.ImageButtonClick += new ImageButtonClick(NavClick); buttonGroup.Left = ; buttonGroup.Top = sum; buttonGroup.ItemMeunClick += ButtonGroup_ItemMeunClick; this.pnlMain.Controls.Add(buttonGroup); bgPre = buttonGroup; }
} private void NavClick(object sender,string moduleName)
{
NavButtonClick?.Invoke(sender, moduleName);
} private void ButtonGroup_ItemMeunClick(object sender, EventArgs e)
{
Label lblItem = sender as Label; currentItemIndex = ; if (lblItem != null)
{
ButtonGroup bg = lblItem.Parent as ButtonGroup; if (bg != null)
{
currentItemIndex = Convert.ToInt32(bg.Tag);
} }
ResetMenu();
} private void ResetMenu()
{
if (listGroup != null && listGroup.Count > )
{
int barHeight = ; int totalHeight = pnlMain.Height; for (int n = ; n < listGroup.Count; n++)
{ ButtonGroup buttonGroup = listGroup[n]; int thisIndex = Convert.ToInt32(buttonGroup.Tag); if (thisIndex <= currentItemIndex)
{
buttonGroup.Top =n * barHeight;
}
else
{
buttonGroup.Top = totalHeight - (listGroup.Count-n) * barHeight;
}
if (thisIndex == currentItemIndex)
{
buttonGroup.Height = totalHeight - (listGroup.Count - ) * barHeight;
}
else
{
buttonGroup.Height = barHeight;
}
} }
} #region ButtonGroup
public class ButtonGroup : UserControl
{
private Label lblItem = new Label(); private string text; private Panel ButtonArea = new Panel(); public event EventHandler ItemMeunClick; public event ImageButtonClick ImageButtonClick; public ButtonGroup(string txt,List<ImageButton> listImageButton)
{
this.text = txt;
this._listImageButton = listImageButton; this.Initialize();
} private List<ImageButton> _listImageButton; public List<ImageButton> ListImageButton
{
get { return _listImageButton; }
set { _listImageButton = value; }
} public void Initialize()
{
lblItem.Text = this.text;
lblItem.Height = ;
lblItem.Width = ;
lblItem.TextAlign = ContentAlignment.MiddleCenter;
lblItem.BackColor = Color.DarkGray;
lblItem.ForeColor = Color.DarkRed;
lblItem.Cursor = Cursors.Hand;
lblItem.Click += LblItem_Click; this.Width = ;
this.BackColor = Color.DarkOliveGreen;
this.Controls.Add(lblItem);
this.Controls.Add(ButtonArea);
} private void LblItem_Click(object sender, EventArgs e)
{
ItemMeunClick?.Invoke(sender, e);
} public void SetButtonLocation()
{
ButtonArea.Location = new Point(, ); int buttonCount = _listImageButton == null ? : _listImageButton.Count; int Height = ;
//ButtonArea.BackColor = Color.Red;
ButtonArea.Size = new Size(, buttonCount * Height);
if (_listImageButton != null && _listImageButton.Count > )
{ for (int i = ; i < _listImageButton.Count; i++)
{
var imgButton = _listImageButton[i]; imgButton.Top = i * imgButton.Height;
imgButton.Left = ; imgButton.PictureBoxClick += ImgButton_PictureBoxClick; ButtonArea.Controls.Add(imgButton);
}
} this.Height = lblItem.Height + ButtonArea.Height; } private void ImgButton_PictureBoxClick(object o, string moduleName)
{
ImageButtonClick?.Invoke(o, moduleName);
}
}
#endregion #region ImageButton
public class ImageButton : UserControl
{ private string text; private Image img; private PictureBox picBox=new PictureBox();
private Label lblText = new Label(); public event ImageButtonClick PictureBoxClick; public ImageButton(string txt, Image image)
{
this.text = txt;
this.img = image; this.InitialImageButtonControl();
} public void InitialImageButtonControl()
{ picBox.Size = new Size(, );
picBox.Left = ;
picBox.Top = ;
picBox.Image = this.img;
picBox.Anchor = AnchorStyles.Top;
picBox.SizeMode = PictureBoxSizeMode.StretchImage;
picBox.Cursor = Cursors.Hand;
picBox.Click += new EventHandler(PicBoxClick); lblText.Width = ;
lblText.Height = ;
lblText.Location = new Point(, );
lblText.Text = this.text;
lblText.TextAlign = ContentAlignment.MiddleCenter;
lblText.BackColor = Color.DarkOliveGreen;
lblText.ForeColor = Color.DarkGray;
lblText.Cursor = Cursors.Hand; this.Height = picBox.Height + lblText.Height;
this.Controls.Add(picBox);
this.Controls.Add(lblText);
} private void PicBoxClick(object sender,EventArgs args)
{ PictureBoxClick?.Invoke(sender, this.text);
} }
#endregion }
 

C# Winform 自定义控件——竖着的Navbar的更多相关文章

  1. C# winform 自定义控件

    近来因为项目的问题,开始研究winform自定义控件,这篇主要是将自定义控件的属性在属性编辑器中可编辑,如果你对自定义控件比较了解的,就不用继续往下看了 首先,我创建了一个类UserButton,继承 ...

  2. C#winform自定义控件模拟设计时界面鼠标移动和调节大小、选中效果

    要想玩转Winform自定义控件需要对GDI+非常熟悉,对常用的控件有一些了解,好选择合适的基类控件来简化. 要点说明及代码 1)定义接口: using System; using System.Wi ...

  3. Winform自定义控件实例

    本文转自http://www.cnblogs.com/hahacjh/archive/2010/04/29/1724125.html 写在前面: .Net已经成为许多软件公司的选择,而.Net自定义W ...

  4. winform 自定义控件:半透明Loading控件

    winform  自定义控件:半透明Loading控件 by wgscd date:2015-05-05 效果: using System;using System.Drawing;using Sys ...

  5. c#Winform自定义控件-目录

    前提 入行已经7,8年了,一直想做一套漂亮点的自定义控件,于是就有了本系列文章. 开源地址:https://gitee.com/kwwwvagaa/net_winform_custom_control ...

  6. (二)c#Winform自定义控件-按钮

    前提 入行已经7,8年了,一直想做一套漂亮点的自定义控件,于是就有了本系列文章. 开源地址:https://gitee.com/kwwwvagaa/net_winform_custom_control ...

  7. (三)c#Winform自定义控件-有图标的按钮

    前提 入行已经7,8年了,一直想做一套漂亮点的自定义控件,于是就有了本系列文章. 开源地址:https://gitee.com/kwwwvagaa/net_winform_custom_control ...

  8. (四)c#Winform自定义控件-选择按钮组

    前提 入行已经7,8年了,一直想做一套漂亮点的自定义控件,于是就有了本系列文章. 开源地址:https://gitee.com/kwwwvagaa/net_winform_custom_control ...

  9. (七)c#Winform自定义控件-进度条

    前提 入行已经7,8年了,一直想做一套漂亮点的自定义控件,于是就有了本系列文章. 开源地址:https://gitee.com/kwwwvagaa/net_winform_custom_control ...

随机推荐

  1. leetcode的Hot100系列--461. 汉明距离

    求两个数的二进制位不同的位置,最先想到的就是异或操作, 异或:按位运算,相同为0,不同为1. 比如: a = 6 对应的二进制表示为: 0 0 1 1 1 ​ b = 9 对应的二进制表示为: 0 1 ...

  2. XAML与C#与WPF三者到底有什么关系?

    XAML是.NET体系开发程序或者网页时前台编程的一种布局方式或者说开发语言,可以比较自由的用标签的方式进行布局,借鉴了HTML和XML等语言的风格,并且加入了一些动画等的实现.C#则是后台逻辑开发用 ...

  3. 【Aizu - 0121】Seven Puzzle (反向bfs)

    -->Seven Puzzle 原文是日语 这里就直接写中文了  Descriptions: 7拼图由8个正方形的卡和这些卡片完全收纳的框构成.每张卡都编号为0, 1, 2, …, 7,以便相互 ...

  4. 微信小程序开发--组件(3)

    一.radio <radio-group class="radio-group" bindchange="radioChange"> <lab ...

  5. MyBatis从入门到精通:第一章的pom.xml文件

    <?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://mave ...

  6. 异常:带有 CLSID {} 的 COM 对象无效或未注册

    今天处理调试打印程序的时候,看到这个异常: 代码: try { string strApplyEmpno=""; string strApplyDeptCode="&qu ...

  7. [原创]Zabbix3.4_API的python示例

    说明: 1.python版本为:python2.7 2.zabbix版本为:zabbix3.4 3.通过python脚本调用zabbix的api接口可以实现批量增删改查主机的信息. 示例如下: #-* ...

  8. 宽字符转窄字符CW2AEX<>(szAreaInfo,CP_UTF8)

    CString szAreaInfo; CW2AEX<>(szAreaInfo,CP_UTF8); 最好能像上面这样转换,否则汉字就会转成乱码.

  9. UVA10071 Back to High School Physics:题解

    题目链接:https://www.luogu.org/problemnew/show/UVA10071 题意简叙: 粒子从0速度提速到t时速度为v,求出2*t时所运动的距离 分析: 这道题是一道物理题 ...

  10. 个人永久性免费-Excel催化剂功能第74波-批量排版格式利器,瞬间美化表格

    PPT和WORD的世界,充满着排版的美化操作,在Excel世界同样也需要对表格.图表的美化,此篇带你进入真正的制表专家行列,使用Excel催化剂的格式管理增强功能加上对美感的艺术造诣,对Excel表格 ...