首页 > 编程语言 >C# wpf 实现自定义撤销重做功能

C# wpf 实现自定义撤销重做功能

时间:2024-03-24 12:56:22浏览次数:26  
标签:index sender 自定义 C# void steps mouseDownMargin wpf public

新建wpf项目,新建Undoable.cs(操作记录),main.xaml(页面)

using System;
using System.Collections.Generic;
namespace WpfApp1
{
    /// <summary>
    /// 撤销重做对象
    /// ceate by xin 2022.6.26
    /// 2023.9.13去除Step的定义替换为KeyValuePair简化实现
    /// </summary>
    public class Undoable
    {
        /// <summary>
        /// 撤销
        /// </summary>
        public void Undo()
        {
            if (index > -1) _steps[index--].Key();
        }
        /// <summary>
        /// 重做
        /// </summary>
        public void Redo()
        {
            if (index < _steps.Count - 1) _steps[++index].Value();
        }
        /// <summary>
        /// 清除
        /// </summary>
        public void Clear()
        {
            _steps.Clear();
            index = -1;
        }
        /// <summary>
        /// 添加操作
        /// </summary>
        /// <param name="undo">撤销</param>
        /// <param name="redo">重做</param>
        public void Add(Action undo, Action redo)
        {
            if (++index < _steps.Count) _steps.RemoveRange(index, _steps.Count - index);
            _steps.Add(new KeyValuePair<Action, Action>(undo, redo));
        }
        //记录的步骤
        List<KeyValuePair<Action, Action>> _steps = new List<KeyValuePair<Action, Action>>();
        //当前操作的下标
        int index = -1;
    }
}
<Window x:Class="WpfApp1.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:WpfApp1"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">
    <Grid>
        <StackPanel Orientation="Horizontal" VerticalAlignment="Top" >
            <Button Width="70" Height="20" Content="撤销"  Click="Button_Click"></Button>
            <Button  Width="70" Height="20" Content="重做" Click="Button_Click_1"></Button>
        </StackPanel>
        <Rectangle   Width="240" Height=" 120"  RadiusX="20" RadiusY="20" Fill="RoyalBlue"  PreviewMouseDown="Rectangle_PreviewMouseDown" 
          PreviewMouseMove="Rectangle_PreviewMouseMove" 
          PreviewMouseUp="Rectangle_PreviewMouseUp"></Rectangle>
        <Ellipse  HorizontalAlignment="Left" Width="120" Height=" 120"   Fill="GreenYellow"  PreviewMouseDown="Rectangle_PreviewMouseDown" 
          PreviewMouseMove="Rectangle_PreviewMouseMove" 
          PreviewMouseUp="Rectangle_PreviewMouseUp"></Ellipse>
    </Grid>
</Window>
using System.Windows;
using System.Windows.Input;
namespace WpfApp1
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        Undoable _undoable = new Undoable();
        //鼠标是否按下
        bool _isMouseDown = false;
        //鼠标按下的位置
        Point _mouseDownPosition;
        //鼠标按下控件的Margin
        Thickness _mouseDownMargin;
        public MainWindow()
        {
            InitializeComponent();
        }
        private void Rectangle_PreviewMouseDown(object sender, MouseButtonEventArgs e)
        {
            var c = sender as FrameworkElement;
            _isMouseDown = true;
            _mouseDownPosition = e.GetPosition(this);
            _mouseDownMargin = c.Margin;
            c.CaptureMouse();
        }

        private void Rectangle_PreviewMouseMove(object sender, MouseEventArgs e)
        {
            if (_isMouseDown)
            {
                var c = sender as FrameworkElement;
                var pos = e.GetPosition(this);
                var dp = pos - _mouseDownPosition;
                c.Margin = new Thickness(_mouseDownMargin.Left + dp.X, _mouseDownMargin.Top + dp.Y, _mouseDownMargin.Right - dp.X, _mouseDownMargin.Bottom - dp.Y);
            }
        }
        private void Rectangle_PreviewMouseUp(object sender, MouseButtonEventArgs e)
        {
            var c = sender as FrameworkElement;
            _isMouseDown = false;
            c.ReleaseMouseCapture();
            var oldMargin = _mouseDownMargin;
            var newMargin = c.Margin;
            _undoable.Add(() => {
                //撤销     
                c.Margin = oldMargin;
            }, () => {
                //重做
                c.Margin = newMargin;
            });
        }
        private void Button_Click(object sender, RoutedEventArgs e)
        {
            _undoable.Undo();
        }
        private void Button_Click_1(object sender, RoutedEventArgs e)
        {
            _undoable.Redo();
        }
    }
}

 

标签:index,sender,自定义,C#,void,steps,mouseDownMargin,wpf,public
From: https://www.cnblogs.com/itsone/p/18092279

相关文章

  • CUDA编程入门历险记
    说来惭愧,做CUDA相关工作已经有两年多,但是对CUDA编程的研究并不深入,最近想夯实一下基础,于是找了一个教程“cudacrashcourse“。这个教程在B站和youtube上都有:B站:https://www.bilibili.com/video/BV127411G76m?p=1&vd_source=5d09aad9eacf6d90c0a17cf81ee41eefyoutube:https://w......
  • CF1896C Matching Arrays 题解
    题目简述给定两个长度为$n$的数列$a,b$,再给定一个数$x$,请你判断是否存在一种重排$b$数列的方式,使得满足$a_i>b_i$的$i$恰好有$x$个。$n\leq2\times10^5$。题目分析遇到这种可行性问题,首先考虑做出最优解,以此来判断是否无解。接下来,可以思考最优解如何构造,我们......
  • CF1468J Road Reform 题解
    题目简述给定一个有$n$个节点,$m$条无向带权边的图,和一个参数$k$,第$i$条边权值为$s_i$。现在你要保留这个图中的$n-1$条边使得这个图变成一棵树,然后你可以对这棵树上的任意边进行修改,每次修改可以使这个边的权值加上一或减去一。现在你需要使所有边权的最大值正好等于......
  • c语言程序实验——实验报告二
    c语言程序实验————实验报告二实验项目名称:实验报告2数据描述实验项目类型:验证性实验日期:2024年3月21日一、实验目的1、掌握C语言数据类型,熟悉如何定义一个整型、字符型和实型的变量,以及对它们赋值的方法。2、掌握不同数据类型之间赋值的规律。3、学会使用C的有关算术运......
  • TCP/UDP/IP协议 自述
    TCP包协议格式SYN—为1表示这是连接请求或是连接接受请求,用于创建连接和使顺序号同步ACK—为1表示确认号字段有效TCP协议三次握手流程主要就是SYN和ACK字段。服务器开始属于监听状态。1、客户端发送连接请求。SYN置为1.序列号为12342、服务器收到请求。ACK置为1,确......
  • socket(五)IDEA与socket
    socket(五)IDEA与socket在IDEA处,我们完成服务器的任务main:首先我们需要在main函数里面创建serverpackageorg.example;importjava.io.IOException;importjava.security.Provider;publicclassMain{publicstaticvoidmain(String[]args)throwsIOExce......
  • wpf datatemplate
    //xaml<Windowx:Class="WpfApp13.MainWindow"xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"xmlns:d="http://schemas.mic......
  • 银行监管报送系统介绍(五):金融统计数据大集中自动化报送系统——PBOC Report
    人民银行金融统计数据大集中自动化报送系统(简称PBOCReport),是基于现代计算机网络技术应用基础上,由人行总行设置金融统计数据服务器,建立的一个全国统一的金融统计数据库。人行针对各银行存贷款、中间业务、网点人员、互联网金融等汇总报表统计,贷款类报表较多,从行业、期限、业务......
  • Lecture 11 Geometry 2 (Curves and Surfaces)
    Lecture11Geometry2(CurvesandSurfaces)Curves曲线BézierCurves贝塞尔曲线用一系列控制点定义摸一个曲线,这些控制点会定义曲线满足的一些性质图中通过三个控制点,可以定义曲线起始点和结束点一定在\(p_0\)和\(p_3\)上,并且起始的切线和结束的切线一定都是\(p_0p_1\)......
  • STM32G431RBT6之ADC06
    电位器调节ADC信号&&ADC调节占空比引脚配置新建文件badc.h&&badc.c#include"badc.h"doublegetADC(ADC_HandleTypeDef*pin){uintadc;HAL_ADC_Start(pin);adc=HAL_ADC_GetValue(pin);returnadc*3.3/4096;}#ifndef_BADC_H_#......