zoukankan      html  css  js  c++  java
  • 项目中撤消与反撤消实现

      最近运维提出要实现撤销与反撤销的功能:

    背景与图片示例。运行图如下:

    针对上图,右键可以实现的如下功能

      针对右键的功能可以对dev中的GridControl插入、剪切、删除等操作。操作过程中可能出错,需要返回上一步。

    实现思路。使用Stack(后进先出),使用图像表示。

    BackDataTable记录每一步的操作。如下图所示

    当按下返回按键时,BackDataTable中的数据pop出栈,push压入AfterDataTable栈中.如下图所示

    当按下返回按键时,AfterDataTable中的数据pop出栈,push压入BackDataTable栈中.

      

    实现代码:

    代码段一:在程序加载时,即Load事件中初始化和注册事件。

                //撤销和反撤销有关信息
                BackDataTable.Clear();            //清空堆栈
                AfterDataTable.Clear();           //清空堆栈
                simBtnBack.Visible = false;       //回退按钮不可见
                simBtnAfter.Visible = false;      //前进按钮不可见
                simBtnBack.Enabled = false;       //回退按钮不可用
                simBtnAfter.Enabled = false;      //前进按钮不可用
    
                simBtnBack.Click += (obj, arg) => 
                      UnDoBeforeOrAfter(ref BackDataTable, ref AfterDataTable, true); //注册回退按纽事件 simBtnAfter.Click += (obj, arg) =>
                      UnDoBeforeOrAfter(ref BackDataTable, ref AfterDataTable, false); //注册前进按纽事件 loaded = true; this.KeyDown += (obj, key) => { if (key.Control && key.KeyCode == Keys.Z) // 撤销 UnDoBeforeOrAfter(ref BackDataTable, ref AfterDataTable, true); if (key.Control && key.KeyCode == Keys.Y) // 反撤销 UnDoBeforeOrAfter(ref BackDataTable, ref AfterDataTable, false); };


    代码段二:获取数据保存每一步操作的数据

                    var table = this.gridOperatorTask.DataSource as DataTable;    
                    if (table != null)
                    {
                        var copy = table.Copy();
                        if (!BackDataTable.Contains(copy))
                        {
                            BackDataTable.Push(copy);          //数据入栈
                        }
                        simBtnBack.Visible = BackDataTable.Count > 0;
                        simBtnBack.Enabled = BackDataTable.Count > 0;
    
                    }

    代码段三:UnDoBeforeOrAfter函数的实现

            private void UnDoBeforeOrAfter(ref Stack<DataTable> backDataTable, ref Stack<DataTable> afterDataTable, bool flag)
            {
                DataTable dt = null;
                FlagUndo = false;
                if (flag)   //撤销 
                {
                    if (backDataTable.Count <= 0)
                        return;
                    dt = backDataTable.Pop();   //出栈
                    afterDataTable.Push(dt);    //入栈
                    simBtnBack.Enabled = backDataTable.Count > 0;
                    simBtnAfter.Visible = AfterDataTable.Count > 0;
                    simBtnAfter.Enabled = afterDataTable.Count > 0;
    
                }
                if (!flag)  //反撤销 
                {
                    if (afterDataTable.Count <= 0)
                        return;
                    dt = afterDataTable.Pop();  //出栈
                    backDataTable.Push(dt);     //入栈
                    simBtnBack.Enabled = backDataTable.Count > 0;
                    simBtnAfter.Enabled = afterDataTable.Count > 0;
                }
                var dtTemp = gridOperatorTask.DataSource as DataTable;
                if (dtTemp == null) return;
                var dtTempCopy = dtTemp.Copy();
                if (dtTempCopy.DataTableEquals(dt))  //DataTableEquals函数是扩展函数
                {
                    gridOperatorTask.DataSource = dt;
                    UnDoBeforeOrAfter(ref BackDataTable, ref AfterDataTable, flag);    //如果出栈的数据与gridOperatorTask.DataSource的数据相同,就递归调用函数
                }
                else
                {
                    gridOperatorTask.DataSource = dt;
                }
            }


    代码段四:DataTableEquals扩展函数的实现       

     图像示意

  • 相关阅读:
    第三章-套接字编程
    unix网络编程第四章----基于TCP套接字编程
    unix网络编程第一章demo
    unix网络编程第2章
    论epoll的实现
    Select函数实现
    函数式编程语言
    Git
    python库-urllib
    PIL处理图片信息
  • 原文地址:https://www.cnblogs.com/zhangyuanbo12358/p/4092727.html
Copyright © 2011-2022 走看看