成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

C#中使用單個對象的方法實現Undo/Redo

開發 后端
本文將告訴我們如何在不同的場景下使用這些方法來實現Undo/Redo,并且幫助大家正確理解Undo/Redo。以及如何使用單個對象表示變化。

簡介

我們如何在不同的場景下使用這些方法來實現Undo/Redo。這些方法是使用單個對象表示變化,命令模式和備忘錄模式。

正如我們所知,Undo/Redo沒有通用的解決方案,而Undo/Redo在每個應用程序中非常具體。處于這個原因,在該系列文章的開始部分,將討論如何使用該方法建模任意的應用程序,然后展示一個簡單應用程序的實現。

關于Undo/Redo實現的基本思想

正如我們所知,應用程序在每次操作后改變其狀態。當操作應用程序時,它的狀態會發生改變。所以,若有人想要做撤銷,他不得不回到先前的狀態。因此,為了能夠回到先前狀態,我們需要在應用程序運行時存儲它的狀態。要支持重做,我們不得不從目前狀態跳到下一個狀態。

為了實現Undo/Redo,我們不得不存儲應用程序的狀態并在撤銷時跳到前一個狀態而在重做時跳到下一個狀態。因此我們需要維護應用程序的狀態來支持Undo/Redo。在所有三種方法中,應用程序狀態的維護用到了兩個棧。一個棧包含用于撤銷操作的狀態,第二個包含用于重做的狀態。撤銷操作彈出撤銷棧以獲取前一個狀態并將其設置給應用程序。同樣的,重做操作彈出重做棧以獲取下一個狀態并將其設置給應用程序。

現在,我們知道了Undo/Redo的實現操作都是關于保持應用程序每次操作后的狀態。現在的問題是該方法如何保存狀態。本方法中,單個操作的改變被保存在一個對象中,有些屬性為該操作作為狀態是多余的,因為這里,單個對象被用于包含所有類型的動作數據。

什么是單個對象表示改變的方法?

首先,我對這是由我命名表示抱歉。這里,單個對象表示了應用程序中所有操作的所有改變。因此,當你準備了一個關于操作更改的類型的對象,在執行一次操作后,你僅使用了該對象屬性的子集,而剩余屬性仍舊沒有被使用。例如,你在一個應用程序中有兩個操作;它們是高度的改變和寬度的改變。因此,對象類型包含兩個屬性:高度和寬度。當你準備了變化對象,在執行高度更改方法后,你僅需設置變化對象的高度字段,而其他字段仍舊沒有被使用。

如何應用單個對象表示變化的方法對任意應用程序Undo/Redo操作建模?

單個對象表示變化的方法如何對任意應用程序Undo/Redo操作建模將在以下步驟中討論:

步驟1

首先識別出你希望哪些操作能支持Undo/Redo。然后,識別出你將在哪個容器下支持Undo/Redo以及你希望哪些對象支持Undo/Redo。

步驟2

為了進一步處理每個Undo/Redo操作,識別出需要被保存的屬性。

步驟3
然后創建一個類(ChangeRepresentationObject),它包含支持全部操作Undo/Redo的所有屬性。同樣,準備一個動作類型enum,它將代表全部操作。這個動作類型enum是ChangeRepresentationObject類的一部分。

步驟4

然后創建一個名為UndoRedo的類,它包含兩個類型的ChangeRepresentationObject棧。一個用于撤銷操作,一個用于重做操作。該類將實現以下接口:

interface IUndoRedo
{
void Undo(int level);
void Redo(int level);
void InsertObjectforUndoRedo(ChangeRepresentationObject dataobject);
}

步驟5

然后實現具體方法:Undo、 Redo、InsertObjectforUndoRedo。

在每個Undo操作中:

◆首先檢查Undo棧是否為空。

◆如果不是,則彈出一個ChangeRepresentationObject并將其壓入重做棧。

◆檢查動作類型。

◆然后基于動作類型,利用ChangeRepresentationObject的屬性完成撤銷操作。
在每個Redo操作中,你幾乎做與Undo同樣的事。

◆首先檢查Redo棧是否為空。

◆如果不是,彈出一個ChangeRepresentationObject,然后將其壓入撤銷棧。

◆檢查動作類型。

◆然后基于動作的類型,利用ChangeRepresentationObject屬性完成重做操作。
在InsertObjectforUndoRedo操作中,你只要把數據對象插入Undo棧并清空Redo棧中。

步驟6

然后,在完成每次操作前,調用InsertObjectforUndoRedo方法以對所有操作提供Undo/Redo支持。在用戶界面上點擊Undo時,只需調用UndoRedo類的Undo方法,而在用戶界面上點擊Redo時,只需調用UndoRedo類的redo方法。

#p#

示例應用程序說明

這個示范WPF繪制應用程序用來作為結合Undo/Redo操作的案例。該WPF應用程序示例支持四種操作:插入對象、刪除對象、移動對象和調整對象的尺寸,它還有兩種類型的幾何對象:矩形和多邊形。它使用畫布作為包含這些幾何對象的容器。

現在,在此系列文章中,我們可以看到如何讓這四個操作支持Undo/Redo。在第一部分,使用單個對象表示變化的方法實現。在第二部分,使用命令模式實現而在第三部分,使用備忘錄模式實現。

使用單個對象表示變化的方法實現示范應用程序的Undo/Redo

利用單個對象表示變化的方法對示范應用程序Undo/Redo的實現將在以下步驟中討論

步驟1

我們將識別出那些需要支持Undo/Redo的操作。這里有四個操作支持Undo/Redo。它們是::插入對象、刪除對象、移動對象和調整對象的尺寸。我們將對矩形和橢圓支持Undo/Redo,這里的容器是畫布。

步驟2

現在我們將識別出那些進一步處理Undo/Redo所需的保存的參數。幾何對象移動時其邊距改變,因此要支持對象移動的Undo/Redo,要保存邊距。當對象改變尺寸時,它的高度、寬度和邊距改變。因此為支持對象尺寸調整的Undo/Redo,我們需要保存高度、寬度和邊距。為了支持插入和刪除的Undo/Redo操作,我們需要保存幾何對象的引用。

步驟3

現在我們得到包含邊距、高度、寬度、動作類型、幾何對象引用的ChangeRepresentationObject以支持所有操作的Undo/Redo。這里的幾何對象引用被保存以便我們在對其進行Undo/Redo時獲取。同樣使動作類型enum代表插入、刪除、移動和調整尺寸操作。此動作類型enum被用作ChangeRepresentationObject的一部分。

CollapseCopy Code
public enum ActionType
{
Delete = 0,
Move = 1,
Resize = 2,
Insert = 3
}
CollapseCopy Code
public class ChangeRepresentationObject
{
public ActionType Action;
public Point Margin;
public double Width;
public double height;
public FrameworkElement UiElement;
}

這里,已附上使用單個對象表示變化的方法實現Undo/Redo的項目。

步驟4&5

然后我們將包含兩個ChangeRepresentationObject類型的棧的類命名為UndoRedo。一個棧用于撤銷操作而另一個用于重做操作。類的代碼如下:

CollapseCopy Code
public partial class UnDoRedo : IUndoRedo
{
private Stack _UndoActionsCollection =
 new Stack();
private Stack _RedoActionsCollection =
 new Stack();

#region IUndoRedo Members

public void Undo(int level)
{
for (int i = 1; i <= level; i++)
{
if (_UndoActionsCollection.Count == 0) return;

ChangeRepresentationObject Undostruct = _UndoActionsCollection.Pop();
if (Undostruct.Action == ActionType.Delete)
{
Container.Children.Add(Undostruct.UiElement);
this.RedoPushInUnDoForDelete(Undostruct.UiElement);
}
else if (Undostruct.Action == ActionType.Insert)
{
Container.Children.Remove(Undostruct.UiElement);
this.RedoPushInUnDoForInsert(Undostruct.UiElement);
}
else if (Undostruct.Action == ActionType.Resize)
{
if (_UndoActionsCollection.Count != 0)
{
Point previousMarginOfSelectedObject = new Point
 (((FrameworkElement)Undostruct.UiElement).Margin.Left,
((FrameworkElement)Undostruct.UiElement).Margin.Top);
this.RedoPushInUnDoForResize(previousMarginOfSelectedObject,
 Undostruct.UiElement.Width,
Undostruct.UiElement.Height, Undostruct.UiElement);
Undostruct.UiElement.Margin = new Thickness
 (Undostruct.Margin.X, Undostruct.Margin.Y, 0, 0);
Undostruct.UiElement.Height = Undostruct.height;
Undostruct.UiElement.Width = Undostruct.Width;
}
}
else if (Undostruct.Action == ActionType.Move)
{
Point previousMarginOfSelectedObject = new Point
 (((FrameworkElement)Undostruct.UiElement).Margin.Left,
((FrameworkElement)Undostruct.UiElement).Margin.Top);
this.RedoPushInUnDoForMove(previousMarginOfSelectedObject,
 Undostruct.UiElement);
Undostruct.UiElement.Margin = new Thickness
 (Undostruct.Margin.X, Undostruct.Margin.Y, 0, 0);
}
}
}

public void Redo(int level)
{
for (int i = 1; i <= level; i++)
{
if (_RedoActionsCollection.Count == 0) return;

ChangeRepresentationObject Undostruct = _RedoActionsCollection.Pop();
if (Undostruct.Action == ActionType.Delete)
{
Container.Children.Remove(Undostruct.UiElement);
this.PushInUnDoForDelete(Undostruct.UiElement);
}
else if (Undostruct.Action == ActionType.Insert)
{
Container.Children.Add(Undostruct.UiElement);
this.PushInUnDoForInsert(Undostruct.UiElement);
}
else if (Undostruct.Action == ActionType.Resize)
{
Point previousMarginOfSelectedObject = new Point
 (((FrameworkElement)Undostruct.UiElement).Margin.Left,
((FrameworkElement)Undostruct.UiElement).Margin.Top);
this.PushInUnDoForResize(previousMarginOfSelectedObject,
Undostruct.UiElement.Width,
Undostruct.UiElement.Height, Undostruct.UiElement);
Undostruct.UiElement.Margin = new Thickness
 (Undostruct.Margin.X, Undostruct.Margin.Y, 0, 0);
Undostruct.UiElement.Height = Undostruct.height;
Undostruct.UiElement.Width = Undostruct.Width;
}
else if (Undostruct.Action == ActionType.Move)
{
Point previousMarginOfSelectedObject = new Point
 (((FrameworkElement)Undostruct.UiElement).Margin.Left,
((FrameworkElement)Undostruct.UiElement).Margin.Top);
this.PushInUnDoForMove(previousMarginOfSelectedObject,
 Undostruct.UiElement);
Undostruct.UiElement.Margin = new Thickness
(Undostruct.Margin.X, Undostruct.Margin.Y, 0, 0);
}
}
}
public void InsertObjectforUndoRedo(ChangeRepresentationObject dataobject)
{
_UndoActionsCollection.Push(dataobject);_RedoActionsCollection.Clear();
}
 #endregion

步驟6

在完成每個操作前,調用InsertObjectforUndoRedo方法。當用戶界面上Undo被點擊,我們調用UndoRedo類的Undo方法,而當用戶界面上Redo被點擊,我們調用UndoRedo類的redo方法。

這里,我們沒有明確設置Undo棧和Redo棧的大小,因此,應用程序能具有的狀態數目取決于系統的內存。

使用單個對象表示變化的方法時的變更管理

如果你想要用單個對象表示變化的方法來為新的操作支持Undo/Redo時,你不得不作一些改變。你不得不修改表示變化的對象,動作類型Enum并改變Undo/Redo方法的代碼。所以,它的可維護性很低。

使用單個對象表示變化的方法的優缺點

它的優點是實現簡單,而不需要知道任何的設計模式,你就可以實現Undo/Redo。

可維護性很低。代表該方法的對象包含很多額外信息,因為這里,單個對象用來容納所有動作類型的數據。例如,對移動而言,我們只需保存移動相關的數據,而對調整尺寸,我們應該僅保存該操作相關的數據。所以,我們在保存冗余的數據。隨著操作數目的增加,冗余也在增加。這并不是好的面向對象的設計。

【編輯推薦】

  1. C#實用基礎教程
  2. 如何使用C#代碼實現DataTemplate
  3. 詳解C# 4.0中必選參數與可選參數混合的問題
責任編輯:彭凡 來源: ITPUB
相關推薦

2024-04-26 08:46:38

WPF開發UndoRedo

2021-01-28 05:14:40

C#接口簽名

2009-04-03 13:20:05

C#擴展方法調用

2009-08-10 13:34:11

創建C# COM對象

2009-06-18 13:06:59

C#位運算權限管理

2020-12-31 07:31:10

C# 反射數據

2009-08-19 17:00:07

C#實現PrintPa

2009-08-20 14:22:17

C#實現 Contro

2009-08-17 09:50:59

C# ping命令

2019-04-23 15:20:26

JavaScript對象前端

2009-09-07 09:36:29

C# DisposeDispose方法

2024-06-27 12:21:13

2021-03-07 16:37:52

C#應用程序

2021-02-01 12:36:59

C# Channels存儲

2013-03-15 10:37:08

C#

2024-05-16 12:33:37

C#編程指針

2009-03-27 10:10:13

c#遠程啟動遠程管理

2009-08-25 14:26:28

C#播放AVI文件

2009-08-25 16:54:28

C# RichText

2024-05-21 11:09:17

點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 国产精品夜色一区二区三区 | 亚洲一区二区三区免费在线观看 | 成人精品久久久 | 欧美一区二区三区在线看 | 色婷婷亚洲国产女人的天堂 | 午夜视频一区二区三区 | 成人一区在线观看 | 久久久噜噜噜久久中文字幕色伊伊 | 日韩a在线 | 四虎成人免费视频 | 欧美午夜精品 | 激情五月婷婷 | 午夜激情在线视频 | 99久久精品免费看国产四区 | 色爱综合网 | 91国产视频在线观看 | 国产一区二区三区久久久久久久久 | 精品伦精品一区二区三区视频 | 在线日韩欧美 | 亚洲欧美综合精品久久成人 | 黄色网址在线播放 | 国产美女精品视频免费观看 | 99福利视频导航 | 一级毛片网 | 一级二级三级在线观看 | 作爱视频免费观看 | 久久久久久久久国产 | 一级片网站视频 | 中文字幕国产精品视频 | 色综合色综合色综合 | 国产91精品久久久久久久网曝门 | 国产成人精品一区二区三区网站观看 | www.com久久久 | 天堂在线91 | 国产精品午夜电影 | 爱爱小视频 | 91久久国产综合久久91精品网站 | 狠狠操天天操 | 黄色一级毛片 | 国产精品久久久久久久久久三级 | 国产成人精品a视频一区www |