自写控件:滑动呈现控件(实现了两个以上控件间的切换)师傅的

2023-11-18

public class NavigatePanel : Panel
    {
        public enum Direction
        {
            LeftToRight,
            RightToLeft
        }

        private NavigateArgs mArgs;//Navigate参数

        private Dictionary<string, INavigate> mNaviDic;//所有的Navigate的dic集合
        private Dictionary<string, int> mIndexDic;//每个Navigate对应一个id  该id用来决定是左移动还是右移动
        private Dictionary<string, bool> mInitFlagDic;//每个Navigate的flag都为true   只有flag为ture才可以初始化该Navigate

        //*****mCurrent 的key可能会不等于mCurrentKey  
        //那是由于Navigate()函数前,准备数据阶段启动Tick之前,需要把mCurrentKey设为mNext的key
        private INavigate mCurrent;//当前的Navigate对象
        private INavigate mNext;//目标Navigate对象
        private String mCurrentKey;//当前的key

        private int mTotalLength;
        private int mLength;//不需要知道干什么的  只知道他是Tick里面移动的一部分就成
        private Direction mDirection;
        private Timer mTimer;

        /// <summary>
        /// 如果Navigating为true则表明mTimer
        /// 控件为true且执行Tick操作即正在跳转
        /// </summary>
        private bool Navigating
        {
            get { return this.mTimer.Enabled; }
            set { this.mTimer.Enabled = value; }
        }


        public String CurrentKey
        {
            get { return mCurrentKey; }
        }

        
        public NavigatePanel()
        {
            this.Font = new System.Drawing.Font("Microsoft YaHei", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
            // 设置控件基本Style
            this.SetStyle(ControlStyles.ResizeRedraw, true);
            this.SetStyle(ControlStyles.DoubleBuffer, true);
            this.SetStyle(ControlStyles.SupportsTransparentBackColor, true);
            this.SetStyle(ControlStyles.UserPaint, true);
            this.SetStyle(ControlStyles.AllPaintingInWmPaint, true);
            this.UpdateStyles();

            this.Padding = new Padding(0);
            this.mTimer = new Timer();
            this.mTimer.Tick += mTimer_Tick;
        }


        public void Init(List<KeyValuePair<string, INavigate>> controls, string defControl)
        {
            this.InitBase(controls, defControl, NavigateArgsBuilder.BuildLowSpeed());
        }

        public void Init(List<KeyValuePair<string, INavigate>> controls, string defControl, NavigateArgs args)
        {
            this.InitBase(controls, defControl, args);
        }


        /// <summary>
        /// 向目标跳转
        /// 导航时一定会触发BeginShow
        /// </summary>
        /// <param name="nextControl"></param>
        public void Navigate(string nextControl)
        {
            if (string.IsNullOrEmpty(this.mCurrentKey))
                throw new InvalidOperationException("this panel is not inited");

            if (!this.mNaviDic.ContainsKey(nextControl))
                throw new ArgumentException("target is not exist");

            if (nextControl == this.mCurrentKey)//若果目标Navigate==当前的   就不用跳转了
            {
                this.mCurrent.BeginShow(this.GetInitFlag());//nextControl 对应的Control 的BeginShow()EndShow()自会判断是否初始化
                this.mCurrent.EndShow(this.GetInitFlag());
                return;
            }

            //一个小关口,处理一种情况:如果正在跳转,你又摁了跳转的情况
            if (this.Navigating)//如果正在跳转  那么结束跳转   
            {
                this.EndNavigate();
            }

            this.mTotalLength = this.Width;//设置移动的总长度
            this.mLength = 0;
            this.mDirection = GetDirection(nextControl);//根据目标Navigate获取它的出现方向
            this.mNext = this.mNaviDic[nextControl];//设置 this.mNext

            ReadyForNavigate(nextControl);

            //设置Navigating为true  启动mTimer  执行Tick
            this.Navigating = true;
        }

        public INavigate GetINavigate(string key)
        {
            if (this.mNaviDic == null || !this.mNaviDic.ContainsKey(key))
                return null;

            return this.mNaviDic[key];
        }

        /// <summary>
        /// 为跳转做准备 Tick还没执行
        /// </summary>
        /// <param name="nextControl"></param>
        private void ReadyForNavigate(string nextControl)
        {
            this.mNext.UIControl.Size = new Size(this.Width, this.Height);
            this.mNext.UIControl.Margin = new Padding(0);
            this.mNext.UIControl.Padding = new Padding(0);
            this.mNext.UIControl.Location =
                new Point(this.mDirection == Direction.RightToLeft ? this.Width : -1 * this.Width, 0);

            this.SuspendLayout();
            this.mCurrent.UIControl.Dock = DockStyle.None;
            this.mCurrent.UIControl.Location = new Point(0, 0);
            this.mCurrent.UIControl.Size = new Size(this.Width, this.Height);
            this.Controls.Add(this.mNext.UIControl);
            this.ResumeLayout(true);

            this.mCurrentKey = nextControl;//*****这里只是把next的key给了mCurrentKey
            this.mNext.BeginShow(this.GetInitFlag());
            this.mCurrent.BeginHide();
        }

        /// <summary>
        /// 利用正弦函数计算平滑曲线步长值
        /// </summary>
        /// <returns></returns> 
        private int GetStepLength()
        {
            double angle = Math.PI * (this.mArgs.MaxAngle * mLength / mTotalLength) / 180.0;

            int step = this.mArgs.BaseStepLength + (int)(this.mArgs.MaxStepLength * Math.Sin(angle));

            if (this.mDirection == Direction.RightToLeft)
                step *= -1;

            return step;
        }
        

        /// <summary>
        /// 
        /// </summary>
        /// <param name="controls">所有的Navigate</param>
        /// <param name="defControl">默认Navigate对应的key字符串</param>
        /// <param name="args">Navigate所需要的参数</param>
        private void InitBase(List<KeyValuePair<string, INavigate>> controls, string defControl, NavigateArgs args)
        {
            if (controls == null)
                throw new ArgumentNullException("controls");
            //实例化
            this.mNaviDic = new Dictionary<string, INavigate>();
            this.mInitFlagDic = new Dictionary<string, bool>();
            this.mIndexDic = new Dictionary<string, int>();

            //循环塞入数据
            int index = 0;
            foreach (var item in controls)
            {
                this.mNaviDic.Add(item.Key, item.Value);
                this.mInitFlagDic.Add(item.Key, true);
                this.mIndexDic.Add(item.Key, index++);
            }

            this.mArgs = args;//赋值Navigate参数
            this.mTimer.Interval = args.TimerInterval;//设置Interval
            this.mCurrent = this.mNaviDic[defControl];//根据传过来的 默认key  设为当前控件
            this.mCurrentKey = defControl;//设置当前key

            this.mCurrent.UIControl.Location = new Point(0, 0);
            this.mCurrent.UIControl.Size = new Size(this.Width, this.Height);
            this.mCurrent.UIControl.Margin = new Padding(0);
            this.mCurrent.UIControl.Padding = new Padding(0);
            this.mCurrent.UIControl.Dock = DockStyle.Fill;
            this.Controls.Add(this.mCurrent.UIControl);

            this.mCurrent.BeginShow(this.GetInitFlag());//先BeginShow
            this.mCurrent.EndShow(this.GetInitFlag());//后EndShow
            this.SetInitFlagFalse();//设置对应flag为false
        }

        /// <summary>
        /// 获取移动方向
        /// </summary>
        /// <param name="nextControl">要移动到的控件key</param>
        /// <returns></returns>
        private Direction GetDirection(string nextControl)
        {
            if (this.mIndexDic[this.mCurrentKey] < this.mIndexDic[nextControl])//若当前id<要跳转到的id
                return Direction.LeftToRight;                                  //就是从左向右移动

            return Direction.RightToLeft;                                      //else 从右向左移动
        }

        /// <summary>
        /// 获取当前Navigate的flag
        /// </summary>
        /// <returns>只有flag为ture才可以初始化该Navigate</returns>
        private bool GetInitFlag()
        {
            if (this.mInitFlagDic == null || !this.mInitFlagDic.ContainsKey(this.mCurrentKey))
                return true;

            return this.mInitFlagDic[this.mCurrentKey];//返回mInitFlagDic中当前Navigate对应的flag
        }
        /// <summary>
        /// 设置初始化flag为false   由于此时该Navigate对象已经初始化
        /// </summary>
        private void SetInitFlagFalse()
        {
            if (this.mInitFlagDic == null || !this.mInitFlagDic.ContainsKey(this.mCurrentKey))
                return;

            this.mInitFlagDic[this.mCurrentKey] = false;
        }

        /// <summary>
        /// 停止移动
        /// 一般为移动完毕即跳转完毕
        /// </summary>
        private void EndNavigate()
        {
            this.Navigating = false;//设置false

            this.SuspendLayout();//挂起
            this.Controls.Remove(this.mCurrent.UIControl);//移除当前
            this.mNext.UIControl.Location = new Point(0, 0);
            this.mNext.UIControl.Dock = DockStyle.Fill;
            this.ResumeLayout(true);//恢复

            this.mCurrent.EndHide();
            this.mNext.EndShow(this.GetInitFlag());//是否初始化
            this.SetInitFlagFalse();//设置false

            this.mCurrent = this.mNext;//更改当前
            this.mNext = null;//清空next
        }

        /// <summary>
        /// Tick只执行了对控件的移动
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void mTimer_Tick(object sender, EventArgs e)
        {
            int step = GetStepLength();

            this.mLength += Math.Abs(step);

            if (this.mLength >= this.mTotalLength)
            {
                this.EndNavigate();
                return;
            }

            this.SuspendLayout();

            this.mCurrent.UIControl.Left += step;
            this.mNext.UIControl.Left += step;

            this.ResumeLayout(true);
        }

    }


 

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

自写控件:滑动呈现控件(实现了两个以上控件间的切换)师傅的 的相关文章

随机推荐

  • pytorch 多类分割损失 (Generalized Dice Loss)

    引自该文章python 常用函数和自定义函数整理 2 Pytorch相关处理 Generalized Dice Loss相关代码 如有错误 烦请指正 多类分割dice损失 def generalized dice loss pred tar
  • java Socket 简单实现客户端与服务器间通信(仿聊天室)

    java Socket TCP协议简单实现客户端与服务器间的通信 打赏 执行效果 启动服务器和3个客户端 进行群聊和私聊 执行过程 服务端 首先创建服务器套接字ServerSocket对象并绑定端口 启动服务器 然后ServerSocket
  • 电子学会 青少年软件编程(C语言)等级考试二级 训练题汇总

    一 NOI题库 1 6编程基础之一维数组 OpenJudge OpenJudge 题目 1 7编程基础之字符串 OpenJudge OpenJudge 题目 1 8编程基础之多维数组 OpenJudge OpenJudge 题目 1 9编程
  • cookie、session、token的概念以及区别

    http链接都是无状态的 即是说浏览器无法判断这一次登陆和上一次登陆有没有关联 所以引入cookie和session的概念 让http可以判断你是否曾登陆过 cookie Cookie是客户端保存用户信息的一种机制 用来记录用户的一些信息
  • 一次内核hung task分析

    http blog chinaunix net uid 14528823 id 4406510 html 1 内核hung task检测机制由来 我们知道进程等待IO时 经常处于D状态 即TASK UNINTERRUPTIBLE状态 处于这
  • python读取csv中所遇到的中文编码问题

    由于本人准备学习使用一些机器学习算法 第一个是DecisionTree 然后使用到了西瓜案例 因为涉及到讨厌的编码问题 所以找了好多办法去尝试读取csv文件 1 pandas pandas可谓是神奇 用python学习机器学习不可缺少的一个
  • 如何解决WIN10中,进入本地组策略时出现“命名空间已经被定义为存储中另一文件的目标命名空间”

    1 首先 怎么打开组策略 win R gpedit msc 回车 2 当打开组策略时出现如下的提示 当然关闭后还是可以正常使用的 只是如何去掉该提示呢 3 解决办法 引起该问题的原因就是提示的C WINDOWS PolicyDefiniti
  • Linux脚本启动jar包

    这里主要为shell脚本启动部署在服务器中jar包 bin bash 这里可替换为你自己的执行程序 其他代码无需更改 APP NAME demo jar 使用说明 用来提示输入参数 usage echo Usage sh demo sh s
  • Android上层与驱动交互完整篇(二)Hal层篇

    Android上层与驱动交互完整篇 二 Hal层篇 上篇写了I2C驱动如何来编写 但是驱动里并没有交代如何具体的跟设备通信 现在我们在hal层实现这部分逻辑代码 HAL全称Hardware Abstract Layer 硬件抽象层 它向下屏
  • 基于改进二进制粒子群算法的电力系统机组组合——复现

    目录 文章摘要 研究背景 二进制粒子群算法 代码运行效果 本文代码分享 文章摘要 提出了1种改进的BS0 二进制粒子群 方法求解机组组合问题 首先 利用优先顺序法确定初始的机组组合 根据这个结果 确定优化窗口的范围 在此范围内利用BPSO进
  • WebLogic-执行队列

    一 Tuning the Application Server 二 执行队列 Using Work Managers to Optimize Scheduled WorkThis chapter describes how WebLogic
  • K-近邻算法

    一 K 近邻算法 1 介绍 K 近邻算法 K Nearest Neighbor 又叫KNN算法 指如果一个样本在特征空间中的k个最相似的样本中的大多数属于某一个类别 则该样本也属于这个类别 也就是对于新输入的实例 从数据集中找到于该实例最邻
  • Ubuntu:停掉某个网络

    ifconfig 网口名 down 例子如下 ifconfig docker0 down
  • 163_omnicore升级后无法连接

    qq群里转载的 最近由于omnicore要升级 每个要升级的人都在问rpc怎么连不了了 这里统一回复下 1 为什么连不了 这是bitcoin0 18 0更改了rpcallowip自动侦听的功能 必须使用rpcbind指定要侦听的ip 2 怎
  • 约瑟夫问题详解

    约瑟夫问题 有n个人 编号为1 n 从第一个人开始报数 从1开始报 报到m的人会死掉 然后从第m 1个人开始 重复以上过程 在死了n 1个人后 问最后一个人的编号是 暴力 题目传送门 暴力都想不到就真是让人折服了 暴力的话大模拟即可 不是重
  • 列表转链表+链表合并

    列表转链表 思路 生成一个头节点 current指向该节点 再生成新节点 给该节点赋值val 更新current位置 依次类推 class ListNode object def int self val 0 next None self
  • 腾讯28-整数反转

    腾讯28 整数反转leetcode7 给出一个 32 位的有符号整数 你需要将这个整数中每位上的数字进行反转 示例 1 输入 123 输出 321 示例 2 输入 123 输出 321 示例 3 输入 120 输出 21 注意 假设我们的环
  • mac xmind

    1 首先要安装包 XMind For Mac 本人下载的这个版本xmind8update9 2 下载破解包 XMindCrack jar 链接 https pan baidu com s 1jqpodMvKQTNQyenAIy0Y3w 密码
  • vue反向代理解决跨域及部署nginx端口转发解决跨域

    1 前言 本文是为了解决vue反向代理解决跨域及部署服务器nginx端口转发解决跨域 因为踩了不少的坑 百度了很多 也试了太多的方法 最终得以解决 所以记录一下 希望遇到同样问题的友友们可以高效的解决自己项目中遇到的问题 2 为什么会出现跨
  • 自写控件:滑动呈现控件(实现了两个以上控件间的切换)师傅的

    public class NavigatePanel Panel public enum Direction LeftToRight RightToLeft private NavigateArgs mArgs Navigate参数 pri