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. (NO.00005)iOS实现炸弹人游戏(十一):怪物之火精灵

    大熊猫猪·侯佩原创或翻译作品.欢迎转载,转载请注明出处. 如果觉得写的不好请多提意见,如果觉得不错请多多支持点赞.谢谢! hopy ;) 从本篇开始我们一次介绍一下游戏中敌人的制作过程.看过第一篇的小 ...

  2. Java基础---Java---IO流-----BufferedReader、BufferedWriter、缓冲区、装饰设计模式及和继承的区别

    IO流 IO流用来处理设备之间的数据传输 java对数据的操作是过流的方式 流按操作数据分为两种:字节流与字符流 流按流向分为:输入流,输出流. IO流常用基类 字节流的抽象基类:InputStrea ...

  3. React Native网络请求

    很多移动应用都需要从远程地址中获取数据或资源.你可能需要给某个REST API发起POST请求以提交用户数据,又或者可能仅仅需要从某个服务器上获取一些静态内容--以下就是你会用到的东西.新手可以对照这 ...

  4. Android实现登录小demo

    安卓,在小编实习之前的那段岁月里面,小编都没有玩儿过,如果说玩儿过,那就是安卓手机了,咳咳,敲登录的时候有种特别久违的熟悉,这种熟悉的感觉就和当时敲机房收费系统一样,那叫一个艰难啊,不过小编相信,在小 ...

  5. 【一天一道LeetCode】#232. Implement Queue using Stacks

    一天一道LeetCode 本系列文章已全部上传至我的github,地址:ZeeCoder's Github 欢迎大家关注我的新浪微博,我的新浪微博 欢迎转载,转载请注明出处 (一)题目 Impleme ...

  6. Android程序崩溃异常处理框架

    目前我已经把框架放在了github了,地址如下:https://github.com/msdx/android-crash 使用方法见github上面的README.md. 本项目相关jar包已发布在 ...

  7. Java进阶(六)Java反射机制可恶问题NoSuchFieldException

    作为一种重要特性,Java反射机制在很多地方会用到.在此做一小结,供朋友们参考. 首先从一个问题开始着手. 可恶的问题又来了,NoSuchFieldException,如下图所示: 完全不知道这个qu ...

  8. Tensorflow使用Cmake在Windows下生成VisualStudio工程并编译

    传送门: https://github.com/tensorflow/tensorflow/tree/r0.12/tensorflow/contrib/cmake http://www.udpwork ...

  9. Unity UGUI基础之InputField

    InputField(输入域):为文本输入控件,等同于NGUI的Input. 一.InputField组件: Text Component(文本组件):此输入域的文本显示组件,需带有Text组件. T ...

  10. Android官方命令深入分析之etc1tool

    etc1tool是一个命令行工具,可以将PNG图像压缩为etc1标准,并且可以进行解压缩. 用法: etc1tool infile [--help | --encode | --encodeNoHea ...