C# 模仿Windows可摺疊導航欄
阿新 • • 發佈:2019-01-07
先上張效果圖,依次為 全展開圖,部分摺疊圖,全部摺疊圖
程式碼下載
時間倉促,功能相對簡單,也未經過詳細測試,不支援設計期操作,這裡提供思路給大家,有時間完善吧,上程式碼:
程式碼檔案介紹
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";