当前位置:网站首页>C # WPF realizes undo redo function
C # WPF realizes undo redo function
2022-06-27 11:58:00 【CodeOfCC】
List of articles
Preface
do wpf Sometimes you need to undo the redo function in the interface , Although some wpf Control has its own Undo function , However, in some complex scenarios, you still need to implement the undo redo function , For example, custom whiteboards or video clips, etc , This article will introduce how to simply implement an undo redo object , And provide use examples .
One 、 Concrete realization
Because the implementation is relatively simple , Here, the principle is explained in detail . Use one List Set plus a subscript index That is, all functions can be realized .
1、 Complete code
Undoable.cs
using System;
using System.Collections.Generic;
namespace AC
{
/// <summary>
/// Undo redo object
/// ceate by xin 2022.6.26
/// </summary>
public class Undoable
{
/// <summary>
/// revoke
/// </summary>
public void Undo()
{
if (index >-1)
{
_steps[index--].Undo();
}
}
/// <summary>
/// redo
/// </summary>
public void Redo()
{
if (index < _steps.Count-1)
{
_steps[++index].Redo();
}
}
/// <summary>
/// eliminate
/// </summary>
public void Clear()
{
_steps.Clear();
index = -1;
}
/// <summary>
/// Add operation
/// </summary>
/// <param name="undo"> revoke </param>
/// <param name="redo"> redo </param>
public void Add(Action undo, Action redo)
{
index++;
if (index < _steps.Count)
_steps.RemoveRange(index, _steps.Count-index);
_steps.Add(new Step() {
Undo= undo, Redo = redo });
}
// Operation steps
class Step
{
public Action Redo {
set; get; }
public Action Undo {
set; get; }
}
// Record the steps
List<Step> _steps = new List<Step>();
// Subscript of the current operation
int index = -1;
}
}
Two 、 Examples of use
1、 Drag controls
(1)MainWindow.xaml
<Window x:Class="WpfApp3.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:WpfApp3" mc:Ignorable="d" Title="MainWindow" Height="450" Width="800">
<Grid>
<StackPanel Orientation="Horizontal" VerticalAlignment="Top" >
<Button Width="70" Height="20" Content=" revoke " Click="Button_Click"></Button>
<Button Width="70" Height="20" Content=" redo " 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>
(2)MainWindow.xaml.cs
using AC;
using System.Windows;
using System.Windows.Input;
namespace WpfApp3
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
Undoable _undoable=new Undoable();
// Is the mouse pressed
bool _isMouseDown = false;
// Mouse down position
Point _mouseDownPosition;
// Press the button of the control with the mouse 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(() => {
// revoke
c.Margin = oldMargin;
}, () => {
// redo
c.Margin = newMargin;
});
}
private void Button_Click(object sender, RoutedEventArgs e)
{
_undoable.Undo();
}
private void Button_Click_1(object sender, RoutedEventArgs e)
{
_undoable.Redo();
}
}
}
(3) Results the preview

summary
That's what we're going to talk about today , This article briefly introduces the implementation of undo redo , Generally speaking, it is relatively easy , Especially with Action To record the operation , This will be more flexible , You can use it directly lambda As a parameter .
边栏推荐
- The GLM function of R language is used to build a binary logistic regression model (the family parameter is binomial), and the AIC function is used to compare the AIC values of the two models (simple
- 56. Core principle of flutter - flutter startup process and rendering pipeline
- [tcaplusdb knowledge base] Introduction to tcaplusdb tcaplusadmin tool
- Qstype implementation of self drawing interface project practice (I)
- [worthy of collection] centos7 installation MySQL complete operation command
- Unity Shader学习(一)认识unity shader基本结构
- 动态规划【三】(区间dp)石子合并
- The DBSCAN function of FPC package in R language performs density clustering analysis on data, and the plot function visualizes the clustering graph
- MapReduce实战小案例(自定义排序、二次排序、分组、分区)
- Don't miss it. New media operates 15 treasure official account to share
猜你喜欢
![[tcapulusdb knowledge base] tcapulusdb doc acceptance - Introduction to creating game area](/img/b7/2358e8cf1cdaeaba77e52d04cc74d4.png)
[tcapulusdb knowledge base] tcapulusdb doc acceptance - Introduction to creating game area

Excel中输入整数却总是显示小数,如何调整?

0基础了解电商系统如何对接支付渠道
![[tcapulusdb knowledge base] tcapulusdb doc acceptance - create business introduction](/img/a4/c3255ce17516348f703f7f21511555.png)
[tcapulusdb knowledge base] tcapulusdb doc acceptance - create business introduction

pull request

MapReduce practical cases (customized sorting, secondary sorting, grouping, zoning)

Shell script learning notes

The wonderful use of 0 length array in C language
![[tcaplusdb knowledge base] Introduction to tcaplusdb tcaplusadmin tool](/img/ba/f865c99f3ea9e42c85b7e906f4f076.png)
[tcaplusdb knowledge base] Introduction to tcaplusdb tcaplusadmin tool

C語言0長度數組的妙用
随机推荐
15+ urban road element segmentation application, this segmentation model is enough!
Popular science of device review: popular science of innovative medical device series - sternum plate products
R语言使用epiDisplay包的poisgof函数对泊松回归(Poisson Regression)执行拟合优度检验、检验是否存在过度离散问题(overdispersion)
Interviewer: with the for loop, why do you need foreach?
MapReduce实战小案例(自定义排序、二次排序、分组、分区)
R语言使用glm函数构建泊松对数线性回归模型处理三维列联表数据构建饱和模型、使用step函数基于AIC指标实现逐步回归筛选最佳模型、解读分析模型
C# wpf 实现撤销重做功能
$15.8 billion! 2021 the world's top15 most profitable hedge fund giant
【On nacos】快速上手 Nacos
Jerry's seamless looping [chapter]
Heap heap sort TOPK
[tcapulusdb knowledge base] Introduction to tcapulusdb tcapsvrmgr tool (I)
The wonderful use of 0 length array in C language
千万不要错过,新媒体运营15个宝藏公众号分享
R language uses the poisgof function of epidisplay package to test the goodness of fit of Poisson regression and whether there is overdispersion
【TcaplusDB知识库】TcaplusDB运维单据介绍
c/s 架构
【TcaplusDB知识库】TcaplusDB单据受理-创建业务介绍
Redis 分布式锁15问,看看你都掌握了哪些?
MQTT协议栈原理及交互流程图