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

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);
        }

    }


 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值