public class OutlookBar : Panel
    {
        private int SelectedBandHeight { get; set; }

        public int ButtonHeight { get; set; }

        public int SelectedBand { get; set; }

        public OutlookBar()
        {
            ButtonHeight = ;
            SelectedBand = ;
            SelectedBandHeight = ;
        }

        /// <summary>
        /// 初始化位置
        /// </summary>
        public void Initialize()
        {
            Parent.SizeChanged += new EventHandler(SizeChangedEvent);
        }

        /// <summary>
        /// 添加
        /// </summary>
        /// <param name="text"></param>
        /// <param name="panel"></param>
        public void AddBand(string text, Panel panel)
        {
            var index = Controls.Count;
            MainPanel bandPanel = new MainPanel(new Model() { OutlookBar = this, Index = index, Text = text, Panel = panel });

            Controls.Add(bandPanel);
            UpdateBarInfo();
            RecalcLayout(bandPanel, index);
        }

        /// <summary>
        /// 选择
        /// </summary>
        /// <param name="index"></param>
        public void SelectBand(int index)
        {
            SelectedBand = index;
            RedrawBands();
        }

        private void RedrawBands()
        {
            ; i < Controls.Count; i++)
            {
                MainPanel bp = Controls[i] as MainPanel;
                RecalcLayout(bp, i);
            }
        }

        /// <summary>
        /// 更新
        /// </summary>
        private void UpdateBarInfo()
        {
            SelectedBandHeight = ClientRectangle.Height - (Controls.Count * ButtonHeight);
        }

        /// <summary>
        /// 重新计算布局
        /// </summary>
        /// <param name="mainPanel"></param>
        /// <param name="index"></param>
        private void RecalcLayout(MainPanel mainPanel, int index)
        {
            int vPos = (index <= SelectedBand) ? ButtonHeight * index : ButtonHeight * index + SelectedBandHeight;
            int height = SelectedBand == index ? SelectedBandHeight + ButtonHeight : ButtonHeight;

            //主面板尺寸
            mainPanel.Location = , vPos);
            mainPanel.Size = new Size(ClientRectangle.Width, height);

            //计算按钮尺寸
            mainPanel.Controls[].Location = , );
            mainPanel.Controls[].Size = new Size(ClientRectangle.Width, ButtonHeight);

            //计算内容尺寸
            mainPanel.Controls[].Location = , ButtonHeight);
            mainPanel.Controls[].Size = , height - );
        }

        private void SizeChangedEvent(object sender, EventArgs e)
        {
            Size = new Size(Size.Width, ((Control)sender).ClientRectangle.Size.Height);
            UpdateBarInfo();
            RedrawBands();
        }
    }

手风琴 主体代码

class MainPanel : Panel
    {
        public Model model { get; set; }

        public MainPanel(Model obj)
        {
            this.model = obj;

            Button btn = new Button() { Text = obj.Text, FlatStyle = FlatStyle.Standard, Visible = true };
            btn.Click += new EventHandler(SelectBand);

            this.model.Panel.AutoScroll = true;
            this.model.Panel.Dock = DockStyle.Fill;

            Controls.Add(btn);
            Controls.Add(this.model.Panel);
        }
        private void SelectBand(object sender, EventArgs e)
        {
            model.OutlookBar.SelectBand(model.Index);
        }
    }

主体Panel

  class Model
    {
        public OutlookBar OutlookBar { get; set; }

        public int Index { get; set; }

        public string Text { get; set; }

        public Panel Panel { get; set; }
    }

实体类

 private void DataBindBar()
        {
            outlookBar.Initialize();
            var panel1 = new TableLayoutPanel();
            var panel2 = new TableLayoutPanel();
            var panel3 = new TableLayoutPanel();

            outlookBar.AddBand("工具条A", panel1);
            outlookBar.AddBand("工具条B", panel2);
            outlookBar.AddBand("工具条C", panel3);

            ; i <= ; i++)
            {
                panel1.Controls.Add(new Button() { Text = i.ToString() });
            }
            ; i <= ; i++)
            {
                panel2.Controls.Add(new Button() { Text = i.ToString() });
            }
            ; i <= ; i++)
            {
                panel3.Controls.Add(new Button() { Text = i.ToString() });
            }
            outlookBar.SelectBand();
        }

调用方式

效果图:

windows from 手风琴的更多相关文章

  1. Windows server 2012 添加中文语言包(英文转为中文)(离线)

    Windows server 2012 添加中文语言包(英文转为中文)(离线) 相关资料: 公司环境:亚马孙aws虚拟机 英文版Windows2012 中文SQL Server2012安装包,需要安装 ...

  2. Windows Server 2012 NIC Teaming介绍及注意事项

    Windows Server 2012 NIC Teaming介绍及注意事项 转载自:http://www.it165.net/os/html/201303/4799.html Windows Ser ...

  3. C# 注册 Windows 热键

    闲扯: 前几日,一个朋友问我如何实现按 F1 键实现粘贴(Ctrl+V)功能,百度了一个方法,发给他,他看不懂(已经是 Boss 的曾经的码农),我就做了个Demo给他参考.今日得空,将 Demo 整 ...

  4. Windows 7上执行Cake 报错原因是Powershell 版本问题

    在Windows 7 SP1 电脑上执行Cake的的例子 http://cakebuild.net/docs/tutorials/getting-started ,运行./Build.ps1 报下面的 ...

  5. 在离线环境中发布.NET Core至Windows Server 2008

    在离线环境中发布.NET Core至Windows Server 2008 0x00 写在开始 之前一篇博客中写了在离线环境中使用.NET Core,之后一边学习一边写了一些页面作为测试,现在打算发布 ...

  6. Windows平台分布式架构实践 - 负载均衡

    概述 最近.NET的世界开始闹腾了,微软官方终于加入到了对.NET跨平台的支持,并且在不久的将来,我们在VS里面写的代码可能就可以通过Mono直接在Linux和Mac上运行.那么大家(开发者和企业)为 ...

  7. dll文件32位64位检测工具以及Windows文件夹SysWow64的坑

    自从操作系统升级到64位以后,就要不断的需要面对32位.64位的问题.相信有很多人并不是很清楚32位程序与64位程序的区别,以及Program Files (x86),Program Files的区别 ...

  8. 在docker中运行ASP.NET Core Web API应用程序(附AWS Windows Server 2016 widt Container实战案例)

    环境准备 1.亚马逊EC2 Windows Server 2016 with Container 2.Visual Studio 2015 Enterprise(Profresianal要装Updat ...

  9. 1.初始Windows Server 2012 R2 Hyper-V + 系统安装详细

    干啥的?现在企业服务器都是分开的,比如图片服务器,数据库服务器,redis服务器等等,或多或少一个网站都会用到多个服务器,而服务器的成本很高,要是动不动采购几十台,公司绝对吃不消的,于是虚拟化技术出来 ...

随机推荐

  1. 安装解压版本的MySQL,安装过程中的常见命令,检查windows系统错误日志的方式来检查MySQL启动错误,关于Fatal error: Can't open and lock privilege

     以端口 port = 3306 # 设置mysql的安装目录 basedir=D://Installed//mysql-5.6.26-winx64//mysql-5.6.26-winx64 # ...

  2. linux常用的内核镜像格式

    linux常用的内核镜像格式 Linux内核有多种格式的镜像,包括vmlinux.Image.zImage等. 1.     Linux内核镜像格式 1.1 vmlinux vmlinuz是可引导的. ...

  3. 最简单的基于librtmp的示例:接收(RTMP保存为FLV)

    ===================================================== 最简单的基于libRTMP的示例系列文章列表: 最简单的基于librtmp的示例:接收(RT ...

  4. 【OpenGL】理解一些基本问题

    写在前面 啦啦啦,搞了很久的Unity Shaders,越学越觉得基础知识很重要.学Unity Shader的时候,总会想,shader到底是什么呢?shader的pipeline是什么呢?它们是怎么 ...

  5. linux内核cfs浅析

    linux调度器的一般原理请参阅<linux进程调度浅析>.之前的调度器cfs之前的linux调度器一般使用用户设定的静态优先级,加上对于进程交互性的判断来生成动态优先级,再根据动态优先级 ...

  6. 后端分布式系列:分布式存储-HDFS 与 GFS 的设计差异

    「后端分布式系列」前面关于 HDFS 的一些文章介绍了它的整体架构和一些关键部件的设计实现要点. 我们知道 HDFS 最早是根据 GFS(Google File System)的论文概念模型来设计实现 ...

  7. iOS中 MediaPlayer framework实现视频播放 韩俊强的博客

    iOS开发中播放音乐可以使用MPMusicPlayerController类来实现,播放视频可以使用MPMoviePlayerController和MPMoviePlayerViewControlle ...

  8. Linux的文件系统及其硬盘分区挂载原理

    如果您是一位新手,也许 您还不知道如何把文件从Windows拷贝到Linux上吧?下面,我们将说明Unix文件系统以及mount的工作过程,然后再比较详细地讨论. mount的使用和有关选项.如果您已 ...

  9. Linux驱动基础:msm平台,modem等framework加载

    msm平台,AP和CP封装在一起,公用一块内存.所以AP需要负责把整个modem, TZ , rpm等binary拷贝到内存中以供modem等subsystem去运行.那AP这边是怎么分配这些内存,又 ...

  10. 《java入门第一季》之好玩的正则表达式

    先不通过正则表达式来判断输入的qq号码是否正确. import java.util.Scanner; /* * 校验qq号码. * 1:要求必须是5-15位数字 * 2:0不能开头 * * 分析: * ...