首页 > 其他分享 >winform 导航栏

winform 导航栏

时间:2023-01-01 16:55:57浏览次数:38  
标签:Color NavBarOption private Tag new 导航 public winform

 搞习惯了B/S的,想把winform的主页面搞成一个类似web网站主页的,首先左侧要有一个导航栏,这个对于winform 来说好像难度有点大了,连直接 拖拽的控件都没有,如果用TreeView的话,那是真的丑,那怎么办呢,只能自己定义一个导航控件了,首先,本人没有艺术细胞,先看看人家框架的导航栏是什么样式的,layui以前用的比较多,那就他了,等一下官网看看盗汗蓝是什么样子的。

 

 上图是官网给的样式,那就照着这个搞一个导航栏,一般导是由图标的,那就在这个基础上加一个图标。这部就妥了吗。

   按照上面的做一个,自己要自定义一个导航栏控件,我在网上先搜了一下,有一位大佬的思路不错,在大佬基础上在升华一次。首先现间一个类NavBar继承 FlowLayoutPanel

然后新建一个Model用来存放标题和子标题的。NavBarOption

 public  class NavBarOption
  {
    public string Title { get; set; }
    public object Tag { get; set; }
    public Image image { get; set; }
    public List<NavBarOption> Item { get; set; }
  }

 然后就是自定义这个组件了:

  public class NavBar: FlowLayoutPanel
  {
    private List<FlowLayoutPanel> childList = new List<FlowLayoutPanel>();//子类集合
    private List<FlowLayoutPanel> parentList = new List<FlowLayoutPanel>();//父类集合
    public event MouseEventHandler ChildItemMouseClick = null;//子项鼠标事件
    public event MouseEventHandler ParentItemMouseClick = null;//父项鼠标事件

    public NavBar()
    {
      this.AutoScroll = true;
      this.Width = 170;
      this.BackColor = Color.FromArgb(20, 30, 39);
      this.Tag = "main";//初始化底层容器的标志,容器内的Panel 的 Tag用于存储折叠展开状态
      SetScrollBar(this.Handle, 1, 0);//隐藏下、右滚动条
      SetScrollBar(this.Handle, 0, 0);
    }
    /// <summary>
    /// 设置子项的字体
    /// </summary>
    [DefaultValue(typeof(Font), "微软雅黑,9pt")]
    [Description("子项的字体")]
    public Font ChildItemFont
    {
      get { return _childItemFont; }
      set { _childItemFont = value; }
    }
    private Font _childItemFont = new Font(new FontFamily("微软雅黑"), 9);

    /// <summary>
    /// 设置父项的字体
    /// </summary>
    [DefaultValue(typeof(Font), "微软雅黑,11pt,style=Bold")]
    [Description("父项的字体")]
    public Font ParentItemFont
    {
      get { return _parentItemFont; }
      set { _parentItemFont = value; }
    }
    private Font _parentItemFont = new Font(new FontFamily("微软雅黑"), 11, FontStyle.Bold);

    /// <summary>
    /// 设置子项的四边边距
    /// </summary>
    [DefaultValue(typeof(Padding), "10,0,0,0")]
    [Description("设置子项的四边边距")]
    public Padding ChiluItemMargin
    {
      get { return _childItemMargin; }
      set { _childItemMargin = value; }
    }
    private Padding _childItemMargin = new Padding(0, 0, 0, 0);
    /// <summary>
    /// 父节点的背景颜色
    /// </summary>
    [DefaultValue(typeof(Color), "57, 61, 73")]
    [Description("父节点的背景颜色")]
    public Color ParentBackColor
    {
      get { return _parentBackColor; }
      set { _parentBackColor = value; }
    }
    private Color _parentBackColor = Color.FromArgb(57, 61, 73);

    /// <summary>
    /// 子节点的背景颜色
    /// </summary>
    [DefaultValue(typeof(Color), "20, 30, 39")]
    [Description("子节点的背景颜色")]
    public Color ChildBackColor
    {
      get { return _childBackColor; }
      set { _childBackColor = value; }
    }
    private Color _childBackColor = Color.FromArgb(20, 30, 39);


    /// <summary>
    /// 父节点的高度
    /// </summary>
    [DefaultValue(typeof(int), "40")]
    [Description("父节点的高度")]
    public int ParentHeight
    {
      get { return _parentHeight; }
      set { _parentHeight = value; }
    }
    private int _parentHeight = 40;


    /// <summary>
    /// 子级节点的高度
    /// </summary>
    [DefaultValue(typeof(int), "30")]
    [Description("子节点的高度")]
    public int ChildHeight
    {
      get { return _childHeight; }
      set { _childHeight = value; }
    }
    private int _childHeight = 30;

    /// <summary>
    /// 鼠标悬浮节点的背景颜色
    /// </summary>
    [DefaultValue(typeof(Color), "39, 51, 69")]
    [Description("鼠标悬浮节点的背景颜色")]
    public Color MouseHoverBackColor
    {
      get { return _mouseHoverBackColor; }
      set { _mouseHoverBackColor = value; }
    }
    private Color _mouseHoverBackColor = Color.FromArgb(39, 51, 69);


    /// <summary>
    /// 子节点被选中字体颜色
    /// </summary>
    [DefaultValue(typeof(Color), "28, 134, 238")]
    [Description("子节点被选中字体颜色")]
    public Color ChildSelectedForeColor
    {
      get { return _childSelectedForeColor; }
      set { _childSelectedForeColor = value; }
    }
    private Color _childSelectedForeColor = Color.FromArgb(255, 255, 255);


    public void SetNavBar(List<NavBarOption> options)
    {
      CreateMenuItemPanels(options, this, _parentHeight, false);
      

    }
    /// <summary>
    /// 创建导航栏项
    /// </summary>
    /// <param name="options">项的设置信息</param>
    /// <param name="parent">项的父容器</param>
    /// <param name="itemH">项的高度</param>
    /// <param name="isChildNode">该项是否输入最终子项</param>
    private void CreateMenuItemPanels(List<NavBarOption> options, FlowLayoutPanel parent, int itemH, bool isChildNode)
    {
      if (options == null || options.Count <= 0) return;
      foreach (NavBarOption option in options)
      {
        FlowLayoutPanel panel = CreatePanel(option, itemH, parent, isChildNode);
        parent.Controls.Add(panel);
        if (option.Item != null && option.Item.Count > 0)
        {
          CreateMenuItemPanels(option.Item, panel, _childHeight, true);
        }
      }

    }
    /// <summary>
    /// 创建项中的控件
    /// </summary>
    /// <param name="option">项的设置信息</param>
    /// <param name="itemH">项高度</param>
    /// <param name="pPanel">项的父容器</param>
    /// <returns></returns>
    private FlowLayoutPanel CreatePanel(NavBarOption option, int itemH, FlowLayoutPanel pPanel, bool isChildNode)
    {
      NavBar panel = new NavBar();
      Label itemL = new Label();

      panel.AutoScroll = false;
      panel.Height = itemH;

      if (isChildNode)
      {
        panel.BackColor = _childBackColor;
        panel.Margin = _childItemMargin;
        childList.Add(panel);
      }
      else
      {
        panel.BackColor = _parentBackColor;
        panel.Margin = new Padding(0);
        parentList.Add(panel);
      }
      panel.Width = pPanel.Width;
      panel.Tag = false;

      if (isChildNode)
      {
        itemL.Font = _childItemFont;
      }
      else
      {
        itemL.Font = _parentItemFont;
      }

      itemL.Text = option.Title;
      itemL.TextAlign = ContentAlignment.MiddleCenter;
      itemL.ImageAlign = ContentAlignment.MiddleLeft;
      itemL.Image = option.image;


      //itemL.BackColor = Color.Empty;
      itemL.ForeColor = Color.White;
      itemL.Height = panel.Height;
      itemL.Width = pPanel.Width;
      itemL.Tag = option;

      //添加鼠标进入与离开事件
      itemL.MouseEnter += ItemL_MouseEnter;
      itemL.MouseLeave += ItemL_MouseLeave;
      //如果该节点的子节点不为空,且子节点数大于0
      if (option.Item != null && option.Item.Count > 0)
      {
        itemL.Paint += ItemL_Paint_Expand;//添加展开与折叠图案绘制
        itemL.MouseClick += ItemL_Parent_MouseClick;//展开与折叠事件
        if (ParentItemMouseClick != null)
        {
          itemL.MouseClick += ParentItemMouseClick;
        }
      }
      else
      {
        itemL.MouseClick += ItemL_Childe_MouseClick;//更改选中状态
        if (ChildItemMouseClick != null)
        {
          itemL.MouseClick += ChildItemMouseClick;
        }
      }

      panel.Controls.Add(itemL);
      return panel;
    }
    #region 设置滚动条显示
    [DllImport("user32.dll", CharSet = CharSet.Auto)]
    public static extern int ShowScrollBar(IntPtr hWnd, int bar, int show);

    private class SubWindow : NativeWindow
    {
      private int m_Horz = 0;
      private int m_Show = 0;

      public SubWindow(int p_Horz, int p_Show)
      {
        m_Horz = p_Horz;
        m_Show = p_Show;
      }
      protected override void WndProc(ref Message m_Msg)
      {
        ShowScrollBar(m_Msg.HWnd, m_Horz, m_Show);
        base.WndProc(ref m_Msg);
      }
    }
    /// <summary>
    /// 设置滚动条是否显示 
    /// </summary>
    /// <param name="p_ControlHandle">句柄</param>
    /// <param name="p_Horz">0横 1列 3全部</param>
    /// <param name="p_Show">0隐 1显</param>
    public static void SetScrollBar(IntPtr p_ControlHandle, int p_Horz, int p_Show)
    {
      SubWindow _SubWindow = new SubWindow(p_Horz, p_Show);
      _SubWindow.AssignHandle(p_ControlHandle);
    }

    #endregion
    private void ItemL_Childe_MouseClick(object sender, MouseEventArgs e)
    {
      Label label = sender as Label;
      NavBarOption option = label.Tag as NavBarOption;
      if (!childList.Contains(label.Parent as FlowLayoutPanel)) return;//如果子项中不包含该控件,则退出

      InitializaAllChildItem();//初始化所有子节点
      label.Font = new Font(_childItemFont.FontFamily, _childItemFont.Size + 1, FontStyle.Bold);
      label.ForeColor = Color.White;
    }
    /// <summary>
    /// 初始化所有子节点
    /// </summary>
    public void InitializaAllChildItem()
    {
      foreach (FlowLayoutPanel item in childList)
      {
        Label l = item.Controls[0] as Label;
        l.Font = _childItemFont;
        l.ForeColor = Color.White;
      }
    }


    private void ItemL_Parent_MouseClick(object sender, MouseEventArgs e)
    {
      if (e.Button == MouseButtons.Left)
      {
        Label label = sender as Label;
        FlowLayoutPanel p = label.Parent as FlowLayoutPanel;

        if ((bool)p.Tag)//折叠
        {
          p.Height = label.Height;
          label.Invalidate();
          p.Tag = false;
        }
        else//展开
        {
          CollapseAllItem();
          p.Height = (p.Controls.Count - 1) * _childHeight + (p.Controls.Count - 1) * (_childItemMargin.Bottom + _childItemMargin.Top) + _parentHeight;
          label.Invalidate();
          p.Tag = true;
        }
      }
    }
    /// <summary>
    /// 折叠所有节点
    /// </summary>
    public void CollapseAllItem()
    {
      foreach (FlowLayoutPanel item in parentList)//折叠所有父节点
      {
        item.Height = _parentHeight;
        foreach (Control itemControl in item.Controls)
        {
          if (itemControl is Label)
          {
            itemControl.Invalidate();
            break;
          }
        }

        item.Tag = false;
      }
    }
    private void ItemL_Paint_Expand(object sender, PaintEventArgs e)
    {
      Label label = sender as Label;
      FlowLayoutPanel panel = label.Parent as FlowLayoutPanel;
      Pen p = new Pen(Color.White, 2);
      //int startP = 5;
      //int drawLW =8;
      int lHeight = label.Height;
      int lWidth = label.Width;
      if ((bool)panel.Tag)//折叠
      {


        e.Graphics.DrawLine(p, lWidth * 7 / 9, lHeight * 2 / 5, lWidth * 15 / 18, lHeight * 3 / 5);
        e.Graphics.DrawLine(p, lWidth * 15 / 18, lHeight * 3 / 5, lWidth * 8 / 9, lHeight * 2 / 5);

      }
      else//展开
      {
    

        e.Graphics.DrawLine(p, lWidth * 15 / 18, lHeight * 3 / 7, lWidth * 8 / 9, lHeight * 4 / 7);
        e.Graphics.DrawLine(p, lWidth * 8 / 9, lHeight * 4 / 7, lWidth * 15 / 18, lHeight * 5 / 7);
      }

    }

    private void ItemL_MouseLeave(object sender, EventArgs e)
    {
      Label label = sender as Label;
      label.BackColor = Color.Empty;
    }

    private void ItemL_MouseEnter(object sender, EventArgs e)
    {
      Label label = sender as Label;
      label.BackColor = _mouseHoverBackColor;
    }
  }

  定义完后,我们重新编译一下,会看到工具箱中出现了这个NavBar的组件:

 

 把控件拖拽到窗体上:

 

 然后填充一下数据:

 public partial class Form1 : Form
  {
    public Form1()
    {
      InitializeComponent();
     CreateNavi();
    }
  


    private void CreateNavi()
    {
      List<NavBarOption> plist = new List<NavBarOption>();
      NavBarOption Poption = new NavBarOption();
      Poption.Tag = false;
      Poption.Title = "父标题1";
      Poption.image = Image.FromFile(@"F:\项目\MES\Mesfrm\MES.Win.UI\Resources\yes.png");
      Poption.Item = new List<NavBarOption>();
      NavBarOption Coption1 = new NavBarOption() { Title = "子标题1", Tag = true, image = Image.FromFile(@"F:\项目\MES\Mesfrm\MES.Win.UI\Resources\yes.png") };
      NavBarOption Coption2 = new NavBarOption() { Title = "子标题2", Tag = true, image = Image.FromFile(@"F:\项目\MES\Mesfrm\MES.Win.UI\Resources\yes.png") };
      Poption.Item.Add(Coption1);
      Poption.Item.Add(Coption2);
      plist.Add(Poption);
     
      NavBarOption Poption1 = new NavBarOption();
      Poption1.Tag = false;
      Poption1.Title = "父标题2";
      Poption1.image = Image.FromFile(@"F:\项目\MES\Mesfrm\MES.Win.UI\Resources\yes.png");
      Poption1.Item = new List<NavBarOption>();
      NavBarOption Coption3 = new NavBarOption() { Title = "子标题3", Tag = true, image = Image.FromFile(@"F:\项目\MES\Mesfrm\MES.Win.UI\Resources\yes.png") };
      NavBarOption Coption4 = new NavBarOption() { Title = "子标题4", Tag = true, image = Image.FromFile(@"F:\项目\MES\Mesfrm\MES.Win.UI\Resources\yes.png") };
      Poption1.Item.Add(Coption3);
      Poption1.Item.Add(Coption4);
      plist.Add(Poption1);
      NavBarOption Poption2 = new NavBarOption();
      Poption2.Tag = false;
      Poption2.Title = "父标题3";
      Poption2.image = Image.FromFile(@"F:\项目\MES\Mesfrm\MES.Win.UI\Resources\yes.png");
      Poption2.Item = new List<NavBarOption>();
      NavBarOption Coption5 = new NavBarOption() { Title = "子标题5", Tag = true, image = Image.FromFile(@"F:\项目\MES\Mesfrm\MES.Win.UI\Resources\yes.png") };
      NavBarOption Coption6 = new NavBarOption() { Title = "子标题6", Tag = true, image = Image.FromFile(@"F:\项目\MES\Mesfrm\MES.Win.UI\Resources\yes.png") };
      Poption2.Item.Add(Coption5);
      Poption2.Item.Add(Coption6);
      plist.Add(Poption2);
      navBar1.ChildItemMouseClick += navBar1_ChildItemMouseClick;
      navBar1.SetNavBar(plist);
    }

    private void navBar1_ChildItemMouseClick(object sender, MouseEventArgs e)
    {
      Label lb = sender as Label;

      NavBarOption nav = lb.Tag as NavBarOption;
      MessageBox.Show(nav.Title);
    }


  }

 运行一下看一看效果:

 

 这里导航栏就成了,看一看是不是和layui差不多了。

 

标签:Color,NavBarOption,private,Tag,new,导航,public,winform
From: https://www.cnblogs.com/zpy1993-09/p/17018259.html

相关文章

  • winform 登录
      最近一直在搞winform,对于我一个经常搞B/S的开发者来说,还是学一下的。不得不说这个winform的原始控件时真的丑,对于我一个用惯了前端框架的人来说时真的难受。我拖拽了......
  • .Net技术栈-网址导航
    业余时间为什么整理这个?内容聚合:不用一个一个搜索,我们很快可以进入常用技术官网提高效率:多看官方文档可以最快,最准确的掌握相关的技术资讯,不用被一些没理解透或者有......
  • C语言江苏大学校园导航系统
    C语言江苏大学校园导航系统2江苏大学校园导航系统的设计与实现2.1题目简述本次课题要求针对江苏大学校园实现一个景点/地点导航系统,提供查看学校地图、查看地点信息查......
  • 导航 IRegionManager
     <Windowx:Class="PrismWpfBlankApp.Views.MainWindow"xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x="http://sche......
  • MAUI新生6.5-导航路由Navigation
    MAUI的Shell导航框架,也是以路由方式进行导航,并提供了两套导航方式,一是如前面章节所述的视觉层次结构,会自动建立导航路由,可以进行不同层次页面的导航切换;二是为页面手动注册......
  • 来自一位十年.net研发老人的吐血整理:.Net技术栈-网址导航
    业余时间为什么整理这个?内容聚合:不用一个一个搜索,我们很快可以进入常用技术官网提高效率:多看官方文档可以最快,最准确的掌握相关的技术资讯,不用被一些没理解透或者有偏......
  • 第144期:flutter的导航和路由
    封面图那些封控做核酸的日子,仿佛还在昨天。这几天核酸检测点撤掉之后,仿佛疫情根本没有发生过一样~导航和路由Flutter提供了一个完整的用于在屏幕之间导航和处理深层链接的系......
  • C# WinForm国际化实现的简单方法
    本文是完善:https://www.jb51.net/article/45675.htm文章描述很详细,重要的代码都贴出来了我帮大家懒到家,将窗口代码和资源文件也传上来到手可运行,直观的了解多......
  • Spring Boot2.x 学习导航大纲以及整合的插件学习(如mybatis/shiro等)-Boot整套前端由0到
    文章目录​​一、导言​​​​第一章、Java环境搭建及常用软件篇​​​​第二章、springboot搭建及学习篇​​​​第三章、springboot整合web篇​​​​第四章、springboot......
  • VUE 系统学习系列:学习导航大纲--VUE整套前端由0到1(关注收藏本博文即可)
    文章目录​​导言​​​​1.写在前面​​​​2.本博客优势​​​​3.前端开发常用网站总结​​​​一、VUE环境搭建篇​​​​二、VUE基础知识篇​​​​三、npm和yarn......