C# 模仿Windows可折叠导航栏
Posted bdmh
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C# 模仿Windows可折叠导航栏相关的知识,希望对你有一定的参考价值。
先上张效果图,依次为 全展开图,部分折叠图,全部折叠图
代码下载
时间仓促,功能相对简单,也未经过详细测试,不支持设计期操作,这里提供思路给大家,有时间完善吧,上代码:
代码文件介绍
NavBar.cs 导航栏主体,继承自 Panel
NavGroup.cs NavBar中的分组,即(控制面板,我的电脑等),继承自Control
NavBarItem.cs 分组中的小项(即区域选项,字体等),继承自Control
NavBarButton.cs 导航栏主体右边的圆形按钮
NavGroupCollection.cs 分组的集合
NavBarItemCollection.cs 分组中小项的集合
NavGroupState.cs 组的状态,收缩还是展开
NavBar.cs
using System;
using System.Collections.Generic;
using System.Drawing.Design;
using System.ComponentModel.Design;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace WindowsApplication1
public partial class NavBar : Panel
private NavGroupCollection _groups;
public NavGroupCollection Groups
get return this._groups;
public NavGroup this[int index]
get
if (index > -1)
return this._groups[index];
else
return null;
private int _selectedIndex = -1;
/// <summary>
/// 选择组的索引
/// </summary>
[DefaultValue(-1)]
public int SelectedIndex
get return this._selectedIndex;
set
this._selectedIndex = value;
this.SelectGroup(value);
private int _groupSpace = 20;
/// <summary>
/// Group间距
/// </summary>
public int GroupSpace
get return this._groupSpace;
set this._groupSpace = value;
private int _groupMargin = 5;
/// <summary>
/// Group边距
/// </summary>
public int GroupMargin
get return this._groupMargin;
set this._groupMargin = value;
private ImageList _smallImageList;
/// <summary>
/// 设置图像列表
/// </summary>
public ImageList SmallImageList
get return this._smallImageList;
set this._smallImageList = value;
public NavBar()
InitializeComponent();
this.BackColor = Color.FromArgb(112, 140, 225);
this._groups = new NavGroupCollection(this);
this.AutoScroll = true;
/// <summary>
/// 根据添加的项,布局
/// </summary>
/// <param name="item"></param>
public void SetLayOut(NavGroup item)
this.SuspendLayout();
this.Controls.Add(item);
if (this._groups.Count == 0)
item.Top = 10;
else
item.Top = this[this._groups.Count - 1].Bottom + this.GroupSpace;
item.Width = this.Width - 2 * this.GroupMargin;
item.Left = (this.Width - item.Width) / 2;
item.Height = item.TitleHeight;
this.ResumeLayout();
//item.Anchor = AnchorStyles.Top | AnchorStyles.Left | AnchorStyles.Right;
/// <summary>
/// 重新布局组件
/// </summary>
public void SetLayOut()
for (int i = 0; i < this._groups.Count; i++)
if (i == 0)
this._groups[i].Top = 10;
else
this._groups[i].Top = this._groups[i - 1].Bottom + this._groupSpace;
this._groups[i].GroupIndex = i;
/// <summary>
/// 添加分组
/// </summary>
/// <returns></returns>
public NavGroup AddGroup()
this._groups.Add();
return this._groups[this._groups.Count - 1];
/// <summary>
/// 删除分组
/// </summary>
/// <param name="item"></param>
public void RemoveGroup(NavGroup item)
int i = item.GroupIndex;
this._groups.Remove(item);
this.Controls.Remove(item);
this.SetLayOut();
/// <summary>
/// 删除指定索引的分组
/// </summary>
/// <param name="index"></param>
public void RemoveGroupAt(int index)
this.Controls.Remove(this._groups[index]);
this._groups.RemoveAt(index);
this.SetLayOut();
/// <summary>
/// 选中指定索引的分组
/// </summary>
/// <param name="index"></param>
private void SelectGroup(int index)
foreach (NavGroup g in this._groups)
if (g.GroupIndex == this._selectedIndex) continue;
g.IsSelected = false;
protected override void OnPaint(PaintEventArgs e)
base.OnPaint(e);
NavGroup.cs
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace WindowsApplication1
public partial class NavGroup : Control
private Rectangle _titleRectangle;
private NavBar _ownerBar;
private NavBarButton _button;
private NavBarItemCollection _items;
public NavBarItemCollection Items
get return this._items;
set this._items = value;
public NavBarItem this[int index]
get
if (index > -1)
return this._items[index];
else
return null;
private NavGroupState _groupState = NavGroupState.expand;
/// <summary>
/// 组的状态
/// </summary>
public NavGroupState GroupState
get return this._groupState;
set
this._groupState = value;
this.SetGroupState(value);
private int _groupIndex;
/// <summary>
/// 组索引
/// </summary>
public int GroupIndex
get return this._groupIndex;
set this._groupIndex = value;
private int _titleHeight = 20;
/// <summary>
/// 标题高度
/// </summary>
public int TitleHeight
get return this._titleHeight;
set
this._titleHeight = value;
this.SetTitleRectangle();
private string _title;
/// <summary>
/// 标题
/// </summary>
public string Title
get return this._title;
set this._title = value;
private Color _titleStartColor = Color.White;
/// <summary>
/// 标题渐变开始色
/// </summary>
public Color TitleStartColor
get return this._titleStartColor;
set
this._titleStartColor = value;
private Color _titleEndColor = Color.FromArgb(199, 211, 247);
/// <summary>
/// 标题渐变结束色
/// </summary>
public Color TitleEndColor
get return this._titleEndColor;
set
this._titleEndColor = value;
private int _itemSpace = 5;
/// <summary>
/// Item间距
/// </summary>
public int ItempSpace
get return this._itemSpace;
set this._itemSpace = value;
private int _itemMargin = 5;
/// <summary>
/// Item边距
/// </summary>
public int ItemMargin
get return this._itemMargin;
set this._itemMargin = value;
private bool _isSelected = false;
/// <summary>
/// 是否选中
/// </summary>
public bool IsSelected
get return this._isSelected;
set
this._isSelected = value;
this.Invalidate();
private ImageList _smallImageList;
public ImageList SmallImageList
get return this._smallImageList;
set this._smallImageList = value;
public NavGroup()
InitializeComponent();
this._title = "新建组";
this.BackColor = Color.FromArgb(214,223,247);
SetTitleRectangle();
this._button = new NavBarButton(this);
this._button.Click += new EventHandler
(
delegate(object sender, EventArgs e)
if (this._groupState == NavGroupState.collapse)
this.GroupState = NavGroupState.expand;
else
this.GroupState = NavGroupState.collapse;
);
this._items = new NavBarItemCollection(this);
public NavGroup(NavBar ownerbar):this()
this._ownerBar = ownerbar;
/// <summary>
/// 设置标题区域
/// </summary>
private void SetTitleRectangle()
this._titleRectangle = new Rectangle(0, 0, this.Width, _titleHeight);
/// <summary>
/// 添加项目
/// </summary>
/// <returns></returns>
public NavBarItem AddItem()
this._items.Add();
return this._items[this._items.Count - 1];
/// <summary>
/// 设置组状态
/// </summary>
/// <param name="value"></param>
private void SetGroupState(NavGroupState value)
if (value == NavGroupState.collapse)
this.Height = this._titleHeight;
else
if (this._items.Count > 0)
this.Height = this._items[this._items.Count - 1].Bottom + this._itemSpace;
this._ownerBar.SetLayOut();
/// <summary>
/// 根据新增项布局
/// </summary>
/// <param name="item"></param>
public void SetLayOut(NavBarItem item)
this.SuspendLayout();
this.Controls.Add(item);
if (this._items.Count == 0)
item.Top = this._titleHeight + 10;
else
item.Top = this[this._items.Count - 1].Bottom + this.ItempSpace;
item.Width = this.Width - 2 * this.ItemMargin;
item.Left = (this.Width - item.Width) / 2;
this.Height = item.Bottom + this.ItempSpace;
this._ownerBar.SetLayOut();
this.ResumeLayout();
/// <summary>
/// 重新布局,这个需要完善
/// </summary>
/// <param name="index"></param>
public void SetLayOut(int index)
for (int i = index + 1; i < this._items.Count; i++)
this._items[i].Top = this._items[i-1].Bottom + this._itemSpace;
protected override void OnClick(EventArgs e)
base.OnClick(e);
this.IsSelected = true;
this._ownerBar.SelectedIndex = this._groupIndex;
protected override void OnMouseUp(MouseEventArgs e)
base.OnMouseUp(e);
if (this._button.ClientRectangle.Contains(e.Location))
this._button.DoClick();
this.Invalidate();
protected override void OnPaint(PaintEventArgs e)
base.OnPaint(e);
SizeF size = e.Graphics.MeasureString(this._title, this.Font);
Font titlefont = new Font(this.Font.FontFamily,this.Font.Size, this.Font.Style | FontStyle.Bold);
//未选中
if (!this._isSelected)
LinearGradientBrush brush = new LinearGradientBrush(this._titleRectangle, this._titleStartColor, this._titleEndColor, 0f);
e.Graphics.FillRectangle(brush, this._titleRectangle);
e.Graphics.DrawString(this._title, titlefont, Brushes.Black, this._titleRectangle.X, this._titleRectangle.Top + (this._titleRectangle.Height - size.Height) / 2);
else
e.Graphics.FillRectangle(new SolidBrush(Color.FromArgb(35, 90, 200)), this._titleRectangle);
e.Graphics.DrawString(this._title, titlefont, Brushes.White, this._titleRectangle.X, this._titleRectangle.Top + (this._titleRectangle.Height - size.Height) / 2);
e.Graphics.DrawRectangle(Pens.White, new Rectangle(0, 0, this.Width - 1, this.Height - 1));
//绘制右侧原型按钮
this._button.Draw(e.Graphics);
protected override void OnResize(EventArgs e)
base.OnResize(e);
SetTitleRectangle();
this._button.SetClientRectangle(this._titleRectangle);
NavBarItem.cs,这里偷了个懒,该组件包含一个PictureBox和Label组件,PictureBox用来显示图标,Lable用来显示文字
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Drawing;
namespace WindowsApplication1
public partial class NavBarItem : Control
/// <summary>
/// 供外部调用项的点击事件
/// </summary>
[Browsable(false)]
public event EventHandler ItemClick;
private Rectangle _imageRectangle;
private PictureBox _picbox;
private Label _titlebox;
private NavGroup _ownerGroup;
/// <summary>
/// 所属组
/// </summary>
public NavGroup OwnerGroup
get return this._ownerGroup;
set this._ownerGroup = value;
private int _itemIndex;
public int ItemIndex
get return this._itemIndex;
set this._itemIndex = value;
private int _imageIndex = -1;
/// <summary>
/// 图标的索引
/// </summary>
public int ImageIndex
get return this._imageIndex;
set
if (this._ownerGroup.SmallImageList == null) return;
if (value >= this._ownerGroup.SmallImageList.Images.Count) return;
this._imageIndex = value;
this._picbox.Image = this._ownerGroup.SmallImageList.Images[this._imageIndex];
this.Invalidate();
private new string _text;
/// <summary>
/// 设置显示文字
/// </summary>
public new string Text
get return this._text;
set
this._text = value;
this._titlebox.Text = value;
this.Invalidate();
public NavBarItem()
InitializeComponent();
this.AutoSize = false;
this.Height = 22;
this.Cursor = Cursors.Hand;
this._titlebox = new Label();
this._titlebox.Parent = this;
this._titlebox.Dock = DockStyle.Fill;
this._titlebox.TextAlign = ContentAlignment.MiddleLeft;
this._titlebox.MouseHover += new EventHandler(this.OnTitleMouseHover);
this._titlebox.MouseLeave += new EventHandler(this.OnTitleMouseLeave);
this._titlebox.Click += new EventHandler(this.OnTitleClick);
this._picbox = new PictureBox();
this._picbox.Parent = this;
this._picbox.Dock = DockStyle.Left;
this._picbox.Width = this.Height;
this._picbox.SizeMode = PictureBoxSizeMode.CenterImage;
this.Text = "新建项目";
public NavBarItem(NavGroup ownergroup)
: this()
this._ownerGroup = ownergroup;
private void OnTitleClick(object sender, EventArgs e)
base.OnClick(e);
if (this.ItemClick != null)
this.ItemClick(this, new EventArgs());
private void OnTitleMouseHover(object sender,EventArgs e)
Control c = (Control)sender;
c.ForeColor = Color.Blue;
c.Font = new Font(c.Font.FontFamily, c.Font.Size, c.Font.Style | FontStyle.Underline);
private void OnTitleMouseLeave(object sender, EventArgs e)
Control c = (Control)sender;
c.ForeColor = SystemColors.ControlText;
c.Font = new Font(c.Font.FontFamily, c.Font.Size, FontStyle.Regular);
NavBarButton.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;
using System.Drawing.Drawing2D;
namespace WindowsApplication1
public class NavBarButton
private NavGroup _navgroup;
private Rectangle _clientRectangle;
public Rectangle ClientRectangle
get return this._clientRectangle;
set this._clientRectangle = value;
public NavBarButton()
public NavBarButton(NavGroup navgroup)
this._navgroup = navgroup;
public event EventHandler Click;
public void SetClientRectangle(Rectangle parentRect)
int i =2;
int w = parentRect.Height;
this._clientRectangle = new Rectangle(parentRect.Width - w + i, parentRect.Top + i, w - 2 * i, w - 2 * i);
public void Draw(Graphics g)
g.SmoothingMode = SmoothingMode.AntiAlias;
g.FillEllipse(Brushes.White, this._clientRectangle);
g.DrawEllipse(Pens.Gray, this._clientRectangle);
Point centerpoint = new Point(this._clientRectangle.X + this._clientRectangle.Width / 2, this._clientRectangle.Y + this._clientRectangle.Height / 2);
int w = this._clientRectangle.Width / 4;
Pen pen = new Pen(Color.Black, 1.6f);
if (this._navgroup.GroupState == NavGroupState.collapse)
g.DrawLine(pen, centerpoint.X, centerpoint.Y, centerpoint.X - w, centerpoint.Y - w);
g.DrawLine(pen, centerpoint.X, centerpoint.Y, centerpoint.X + w, centerpoint.Y - w);
g.DrawLine(pen, centerpoint.X, centerpoint.Y + 4, centerpoint.X - w, centerpoint.Y + w - 4);
g.DrawLine(pen, centerpoint.X, centerpoint.Y + 4, centerpoint.X + w, centerpoint.Y + w - 4);
else
g.DrawLine(pen, centerpoint.X, centerpoint.Y, centerpoint.X - w, centerpoint.Y + w);
g.DrawLine(pen, centerpoint.X, centerpoint.Y, centerpoint.X + w, centerpoint.Y + w);
g.DrawLine(pen, centerpoint.X, centerpoint.Y - 4, centerpoint.X - w, centerpoint.Y + w - 4);
g.DrawLine(pen, centerpoint.X, centerpoint.Y - 4, centerpoint.X + w, centerpoint.Y + w - 4);
public void DoClick()
if (this.Click != null)
this.Click(this, new EventArgs());
NavGroupCollection.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace WindowsApplication1
public class NavGroupCollection :List<NavGroup>
private NavBar _ownerBar;
public NavGroupCollection(NavBar ownerBar):base()
this._ownerBar = ownerBar;
public new void Add(NavGroup item)
this._ownerBar.SetLayOut(item);
base.Add(item);
item.GroupIndex = this.Count - 1;
item.SmallImageList = this._ownerBar.SmallImageList;
public new void Add()
NavGroup item = new NavGroup(this._ownerBar);
this.Add(item);
NavBarItemCollection.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace WindowsApplication1
public class NavBarItemCollection : List<NavBarItem>
private NavGroup _ownerGroup;
public NavBarItemCollection(NavGroup ownerGroup):base()
this._ownerGroup = ownerGroup;
public new void Add(NavBarItem item)
this._ownerGroup.SetLayOut(item);
base.Add(item);
item.ItemIndex = this.Count - 1;
public new void Add()
NavBarItem item = new NavBarItem(this._ownerGroup);
this.Add(item);
NavGroupState.cs
using System;
namespace WindowsApplication1
public enum NavGroupState
expand,
collapse
使用,按钮点击时,写如下代码
NavBarItem item;
navBar1.AddGroup().Title = "控制面板";
item = navBar1[0].AddItem();
item.ImageIndex = 0;
item.Text = "区域选项";
item = navBar1[0].AddItem();
item.ImageIndex = 1;
item.Text = "字体";
item = navBar1[0].AddItem();
item.ImageIndex = 2;
item.Text = "添加硬件";
navBar1.AddGroup().Title = "我的电脑";
item = navBar1[1].AddItem();
item.ImageIndex = 3;
item.Text = "C 盘";
navBar1.AddGroup().Title = "网上邻居";
item = navBar1[2].AddItem();
item.ImageIndex = 4;
item.Text = "本地连接";
item = navBar1[2].AddItem();
item.ImageIndex = 5;
item.Text = "VPN连接";
navBar1.AddGroup().Title = "我的文档";
item = navBar1[3].AddItem();
item.ImageIndex = 6;
item.Text = "文档 A";
item = navBar1[3].AddItem();
item.ImageIndex = 7;
item.Text = "文档 B";
item = navBar1[3].AddItem();
item.ImageIndex = 8;
item.Text = "文档 C";
以上是关于C# 模仿Windows可折叠导航栏的主要内容,如果未能解决你的问题,请参考以下文章