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可折叠导航栏的主要内容,如果未能解决你的问题,请参考以下文章

bootstrap 3折叠导航栏问题,导航栏标题溢出

如何在点击时隐藏可折叠的 Bootstrap 导航栏

bootstrap 4中的堆叠可折叠导航栏

html Bootstrap简单的可折叠导航栏

使 nav-pills 可折叠,就像引导程序中的导航栏一样

分组可折叠导航控制 Windows 商店应用程序?