认知尚浅,如有错误,愿闻其详!
概述
winForm这个技术比较老了,第三方的开源控件也早已不再更新,要钱的又用不了,公司处于对面向的用户群的考量,还是坚决使用winForm去开发。所以自己就不得不去写一些自定义控件,以满足需求。废话不多说,这里就讲一下我制作导航栏的思路与实现。
实现
导航栏是由Label + FlowLayoutPanel 控件组成的,大致结构如下图 :
导航菜单栏构造.png
整个控件是继承自
FlowLayoutPanel
,其中的每个子项底层容器也都是继承自FlowLayoutPanel
的自定义控件。主要是利用了FlowLayoutPanel的流排序,免去了自己去进行控件排序。导航栏中的各个子项的创建通过外部传入规定(可在自定义控件内部定义接口)
的数据集合,然后根据集合生成,区分开父节点、子节点,父节点点击则是展开、折叠节点,绘制展开、折叠状态标志,节点展开需要动态的计算各个节点的高度总和并修改父FlowLayoutPanel控件宽度,以完全显示容器中的子控件,子节点被点击改变状态且执行外部传入子节点点击事件
导航栏-1.png
大致流程如上,整个控件的结构图如上:
在初始化菜单导航栏的时候,通过创建菜单项属性集合,传入控件,进行创建。
List<INavigationBarOption> item = new List<INavigationBarOption>();
for (int i = 0; i < 5; i++)
{
List<INavigationBarOption> citems = new List<INavigationBarOption>();
INavigationBarOption parentPanel = new CNavigationBarOption
{
Title = $"选项{i}",
Tag = i,
};
for (int j = 0; j < 5; j++)
{
INavigationBarOption cItem = new CNavigationBarOption
{
Title = $"子选项{j}",
Tag = j,
};
citems.Add(cItem);
}
parentPanel.ChildItemsOption = citems;
item.Add(parentPanel);
}
cNavigationBar1.ChildItemMouseClick += CNavigationBar1_ChildItemMouseClick;
cNavigationBar1.MenuItems = item;
做类似的控件,最好是将创建的父项与子项使用集合等存储,以便于做工能时批量执行操作。
其次,我们需要开启FlowLayoutPanel 的AutoScroll ,这样才能让其滚动显示超出容器的子项,且要隐藏FlowLayoutPanel 自动显示的滚动条,代码如下:
利用句柄的方式去隐藏
//
SetScrollBar(this.Handle, 1, 0);//右(1)滚动条隐藏(0)
SetScrollBar(this.Handle, 0, 0);//下(0)滚动条隐藏(0)
#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
效果
源于自己比较菜鸡,没有很好地去架构与规划,造成比较多的的功能做起来会比较吃力,甚至没法实现。所以目前该导航栏也就支持二级菜单。
有需要的大家可以移步:我的GitHub
导航菜单栏.gif