Framework / System Layer / Document Object Model / Services / Element History Service

In This Topic
    Element History Service
    In This Topic
    The element history service (or simply history service), is designed to provide elements (and hence documents) with consistent support for Undo and Redo of all operations, which the user or the programmer can possibly perform with an element or element attribute. This service is represented by the NElementHistoryService class. The reason for which the element abstraction has been chosen for base of the history service is that elements can be uniquely identified.
     How it Works

    The history service works as a recorder of operations (user or programmer actions). The abstraction of an operation is represented by the NOperation class. All types of operations, which the history service can record must derive from NOperation.

    The history service maintains two operations stacks:

    • Undo stack - holds the operations which can be undone
    • Redo stack - holds the operations which can be redone

    The history service recording obeys to the following rules:

    • Operations are initially recorded (pushed) in the undo stack. The redo stack is automatically cleared when an operation is recorded in the undo stack.
    • You can undo an operation by calling the Undo method - this will pop the operation from the undo stack and push it in the redo stack.
    • You can redo an operation by calling the Redo method - this will pop the operation from the redo stack and push it in the undo stack.

    The history service can virtually operate with an unlimited number of operations. You can however limit the number of recorded undoable operations by setting the MaxUndoLevels property to the number of actions you want the history service to remember:

    C#
    Copy Code
    // instruct the history service to remember the last 200 actions
    historyService.MaxUndoLevels = 200;
    
    Visual Basic
    Copy Code
    ' instruct the history service to remember the last 200 actions
    historyService.MaxUndoLevels = 200
    
     Primitive Operations

    The Nevron DOM implements a set of primitive operations, which are designed to record any user actions, which can be performed on an element or an element attribute. They can be classified in the following categories:

    You can of course implement your own history operations - the only requirement is that they must be derived from the NOperation class.

     

     

     Transactions

    Transactions are groups of operations, which are undone and redone as if they were a single operation. Transactions are represented by the NTransaction class (derived from NOperation). The history service provides three methods, which help you easily work with transactions - they are:

    • StartTransaction - opens a new transaction. Internally this creates a new transaction and pushes it in the transactions stack. If there is an opened transaction, the history service will automatically record all operations in it (instead of recording them in the undo stack).
    • Commit - closes the last opened transaction. Internally this method pops the last transaction from the transactions stack and pushes it in the undo stack.
    • Rollback - aborts the last opened transaction. Internally this method pops the last transaction from the transactions stack and undoes all operations, which it contains in reverse order. The rollback method does not record any operation in the undo stack. The effect of rollback is that the object state, which is monitored by the history service is reverted to the state when the transaction was started.

    The following code snipped demonstrates a typical transaction based method:

    C#
    Copy Code
    public bool MyTransactionBasedMethod()
    { 
        // start a new transaction 
        historyService.StartTransaction("My transaction");
    
        try
        { 
      // do something that can fail
      ...
        } 
        catch (Exception ex)
        { 
      // if something went wrong - restore the state as 
      // it was when the transaction was started
      historyService.Rollback();
      return false;
        }
    
        // if everything went ok - commit the transaction
        historyService.Commit();
        return true;
    }
    
    Visual Basic
    Copy Code
    Public Function MyTransactionBasedMethod() As Boolean 
        ' start a new transaction 
        historyService.StartTransaction("My transaction")
    
        Try 
      ' do something that can fail
      ... 
        Catch ex As Exception 
      ' if something went wrong - restore the state as 
      ' it was when the transaction was started
      historyService.Rollback()
      Return False
        End Try
    
        ' if everything went ok - commit the transaction
        historyService.Commit()
        Return True
    End Function
    
     Making Custom Elements and Attributes History Aware

    In order to make it easier for you to implement custom elements and attributes, which support history, the NAttribute class and the core INElement implementations found in the respective Nevron product, provide a set of protected methods, which safely call the respective methods of the history service. The following code example demonstrates how to implement a custom history aware attribute:

    C#
    Copy Code
    class MyAttribute : NAttribute
    {
        public bool BoolProperty
        {
      get
      {
           return boolField;
      }
      set
      { 
           if (value == boolField)
                return; 
        
              // fire a property changing event and see if the user allows the change 
           // OnPropertyChanging is implemented by NAttribute 
           if (OnPropertyChanging("BoolProperty", value) == false)
                return; 
        
           // record the property value before it is changed 
           // RecordProperty is implemented by NAttribute
           RecordProperty("BoolProperty"); 
           boolField = value; 
    
           // notify the user that the property has changed
           // OnPropertyChanged is implemented by NAttribute
           OnPropertyChanged("BoolProperty");
      }
        }
    
        private bool boolField;
    }
    
    Visual Basic
    Copy Code
    Class MyAttribute Inherits NAttribute
    
        Public Property BoolProperty() As Boolean
      Get 
           Return boolField 
      End Get 
      Set(ByVal Value As Boolean)
           If Value = boolField Then 
                Return 
           End If 
    
                ' fire a property changing event and see if the user allows the change 
           ' OnPropertyChanging is implemented by NAttribute 
           If OnPropertyChanging("BoolProperty", Value) = False Then 
                Return 
           End If 
       
           ' record the property value before it is changed 
           ' RecordProperty is implemented by NAttribute
           RecordProperty("BoolProperty") 
           boolField = Value 
                
             ' notify the user that the property has changed
           ' OnPropertyChanged is implemented by NAttribute
           OnPropertyChanged("BoolProperty")
      End Set
        End Property
    
        Private boolField As Boolean
    End Class
    
    See Also