DesignerTransaction Class
Provides a way to group a series of design-time actions to improve performance and enable most types of changes to be undone.
For a list of all members of this type, see DesignerTransaction Members.
System.Object
System.ComponentModel.Design.DesignerTransaction
[Visual Basic] MustInherit Public Class DesignerTransaction Implements IDisposable [C#] public abstract class DesignerTransaction : IDisposable [C++] public __gc __abstract class DesignerTransaction : public IDisposable [JScript] public abstract class DesignerTransaction implements IDisposable
Thread Safety
Any public static (Shared in Visual Basic) members of this type are thread safe. Any instance members are not guaranteed to be thread safe.
Remarks
Transactions can track actions that can be undone later. Changes made during a transaction can be reversed by cancelling a transaction, which automatically attempts to reverse each change by setting each changed property to its pre-change value. Transactions can also improve performance during a series of operations by deferring updates to the display until the completion of the transaction.
When a transaction is in progress, some components defer their processing until the transaction has completed by listening to the TransactionOpening and TransactionClosed events. The Properties window, for example, does not update its display after a transaction has opened until the transaction has closed.
To use transactions for undoable or multiple operations, have your designer create a DesignerTransaction for each operation or series of operations which should be undoable. Be careful not to perform actions outside the transactions that might prevent a sequence of undo events from completing successfully.
You can obtain a new DesignerTransaction by calling the CreateTransaction method of an IDesignerHost. Be sure to obtain each DesignerTransaction from the active IDesignerHost in order to correctly integrate with the designer transaction processing mechanism, rather than creating a new DesignerTransaction directly.
To perform an action within a transaction, you must first create a transaction. Then you must call the OnComponentChanging method before each change or set of changes occurs, and the OnComponentChanged method after each change or set of changes occur. Finally, complete and close the transaction by calling the Commit method.
Note When making changes to property values, use the SetValue method of a PropertyDescriptor, which calls the component change methods of the IComponentChangeService and creates a DesignerTransaction representing the change automatically.
To perform a transaction:
- Call CreateTransaction to obtain a DesignerTransaction that can be used to control the transaction.
- Within a try block, for each action that you want to track with a DesignerTransaction, call the OnComponentChanging event, make the change or changes, then call the OnComponentChanged event to signal that the change or changes have been made.
- To complete the transaction, call Commit from within a finally block.
In C#, you can use the using statement rather than a try...finally block, such as in the following example.
using (host.CreateTransaction() {
// do work here
} To cancel and attempt to roll back a transaction before it has been committed, call the Cancel method. When the Cancel method is invoked, the actions tracked by the DesignerTransaction are reversed to attempt to roll back the changes. To undo actions which occurred as part of earlier transactions, you must use the undo command provided by the development environment.
Example
[Visual Basic, C#, C++] The following example program demonstrates how to create a DesignerTransaction from a designer. The designer can optionally display notifications about designer transaction events. To run this sample, compile the source code into a class library, add a reference to the compiled DLL to a project and add the component in the library to the Toolbox by right-clicking the toolbox, clicking Customize Toolbox, and selecting the .dll file that contains the DTComponent sample. Add an instance of the DTComponent to a form while in design mode, and a message box appears asking whether you would like to receive designer transaction event notifications. You may toggle these notifications using the shortcut menu that appears when you right-click an instance of the DTComponent. Transactions are created when you change values using the Properties window. You can also have the designer perform a transaction by clicking Perform Example Transaction on the shortcut menu for the component.
[Visual Basic] Imports System Imports System.ComponentModel Imports System.ComponentModel.Design Imports System.Windows.Forms Imports System.Windows.Forms.Design ' This sample demonstrates how to perform a series of actions in a designer ' transaction, how to change values of properties of a component from a ' designer, and how to complete transactions without being interrupted ' by other activities. ' To run this sample, add this code to a class library project and compile. ' Create a new Windows Forms project or load a form in the designer. Add a ' reference to the class library that was compiled in the first step. ' Right-click the Toolbox in design mode and click Customize Toolbox. ' Browse to the class library that was compiled in the first step and ' select OK until the DTComponent item appears in the Toolbox. Add an ' instance of this component to the form. ' When the component is created and added to the component tray for your ' design project, the Initialize method of the designer is called. ' This method displays a message box informing you that designer transaction ' event handlers are being registered unless you click Cancel. When you set ' properties in the properties window, each change will be encapsulated in ' a designer transaction, allowing the change to be undone later. ' When you right-click the component, the shortcut menu for the component ' is displayed. The designer constructs this menu according to whether ' designer transaction notifications are enabled, and offers the option ' of enabling or disabling the notifications, depending on the current ' mode. The shortcut menu also presents a Perform Example Transaction ' item which will set the values of the component's StringProperty and ' CountProperty properties. You can undo the last designer transaction using ' the Undo command provided by the Visual Studio .NET development environment. Namespace DesignerTransactionSample ' Associate the DTDesigner with this component <DesignerAttribute(GetType(DTDesigner))> _ Public Class DTComponent Inherits System.ComponentModel.Component Private m_String As String Private m_Count As Integer Public Property StringProperty() As String Get Return m_String End Get Set(ByVal Value As String) m_String = Value End Set End Property Public Property CountProperty() As Integer Get Return m_Count End Get Set(ByVal Value As Integer) m_Count = Value End Set End Property Private Sub InitializeComponent() m_String = "Initial Value" m_Count = 0 End Sub 'InitializeComponent End Class 'DTComponent Friend Class DTDesigner Inherits ComponentDesigner Private notification_mode As Boolean = False Private count As Integer = 10 ' The Verbs property is overridden from ComponentDesigner Public Overrides ReadOnly Property Verbs() As DesignerVerbCollection Get Dim dvc As New DesignerVerbCollection() dvc.Add(New DesignerVerb("Perform Example Transaction", AddressOf Me.DoTransaction)) If notification_mode Then dvc.Add(New DesignerVerb("End Designer Transaction Notifications", AddressOf Me.UnlinkDTNotifications)) Else dvc.Add(New DesignerVerb("Show Designer Transaction Notifications", AddressOf Me.LinkDTNotifications)) End If Return dvc End Get End Property Public Overrides Sub Initialize(ByVal component As System.ComponentModel.IComponent) MyBase.Initialize(component) Dim host As IDesignerHost = CType(GetService(GetType(IDesignerHost)), IDesignerHost) If host Is Nothing Then MessageBox.Show("The IDesignerHost service interface could not be obtained.") Return End If If MessageBox.Show("Press the Yes button to display notification message boxes for the designer transaction opened and closed notifications.", "Link DesignerTransaction Notifications?", MessageBoxButtons.YesNo, MessageBoxIcon.Question, MessageBoxDefaultButton.Button1, MessageBoxOptions.RightAlign) = DialogResult.Yes Then AddHandler host.TransactionOpened, AddressOf OnDesignerTransactionOpened AddHandler host.TransactionClosed, AddressOf OnDesignerTransactionClosed notification_mode = True End If End Sub 'Initialize Private Sub LinkDTNotifications(ByVal sender As Object, ByVal e As EventArgs) If notification_mode = False Then Dim host As IDesignerHost = CType(GetService(GetType(IDesignerHost)), IDesignerHost) If Not (host Is Nothing) Then notification_mode = True AddHandler host.TransactionOpened, AddressOf OnDesignerTransactionOpened AddHandler host.TransactionClosed, AddressOf OnDesignerTransactionClosed End If End If End Sub 'LinkDTNotifications Private Sub UnlinkDTNotifications(ByVal sender As Object, ByVal e As EventArgs) If notification_mode Then Dim host As IDesignerHost = CType(GetService(GetType(IDesignerHost)), IDesignerHost) If Not (host Is Nothing) Then notification_mode = False RemoveHandler host.TransactionOpened, AddressOf Me.OnDesignerTransactionOpened RemoveHandler host.TransactionClosed, AddressOf Me.OnDesignerTransactionClosed End If End If End Sub 'UnlinkDTNotifications Private Sub OnDesignerTransactionOpened(ByVal sender As Object, ByVal e As EventArgs) System.Windows.Forms.MessageBox.Show("A Designer Transaction was started. (TransactionOpened)") End Sub 'OnDesignerTransactionOpened Private Sub OnDesignerTransactionClosed(ByVal sender As Object, ByVal e As DesignerTransactionCloseEventArgs) System.Windows.Forms.MessageBox.Show("A Designer Transaction was completed. (TransactionClosed)") End Sub 'OnDesignerTransactionClosed Private Sub DoTransaction(ByVal sender As Object, ByVal e As EventArgs) Dim host As IDesignerHost = CType(GetService(GetType(IDesignerHost)), IDesignerHost) Dim t As DesignerTransaction = host.CreateTransaction("Change Text and Size") ' The code within the using statement is considered to be a single transaction. ' When the user selects Undo, the system will undo everything executed in this code block. Try If (notification_mode) Then System.Windows.Forms.MessageBox.Show("Entering a Designer-Initiated Designer Transaction") End If Dim someText As PropertyDescriptor = TypeDescriptor.GetProperties(Component)("StringProperty") someText.SetValue(Component, "This text was set by the designer for this component.") Dim anInteger As PropertyDescriptor = TypeDescriptor.GetProperties(Component)("CountProperty") anInteger.SetValue(Component, count) count = count + 1 Exit Try Finally t.Commit() End Try If (notification_mode) Then System.Windows.Forms.MessageBox.Show("Designer-Initiated Designer Transaction Completed") End If End Sub 'DoTransaction Protected Overloads Overrides Sub Dispose(ByVal disposing As Boolean) UnlinkDTNotifications(Me, New EventArgs()) MyBase.Dispose(disposing) End Sub 'Dispose End Class 'DTDesigner End Namespace 'DesignerTransactionSample [C#] using System; using System.ComponentModel; using System.ComponentModel.Design; using System.Windows.Forms; using System.Windows.Forms.Design; /* This sample demonstrates how to perform a series of actions in a designer transaction, how to change values of properties of a component from a designer, and how to complete transactions without being interrupted by other activities. To run this sample, add this code to a class library project and compile. Create a new Windows Forms project or load a form in the designer. Add a reference to the class library that was compiled in the first step. Right-click the Toolbox in design mode and click Customize Toolbox. Browse to the class library that was compiled in the first step and select OK until the DTComponent item appears in the Toolbox. Add an instance of this component to the form. When the component is created and added to the component tray for your design project, the Initialize method of the designer is called. This method displays a message box informing you that designer transaction event handlers will be registered unless you click Cancel. When you set properties in the properties window, each change will be encapsulated in a designer transaction, allowing the change to be undone later. When you right-click the component, the shortcut menu for the component is displayed. The designer constructs this menu according to whether designer transaction notifications are enabled, and offers the option of enabling or disabling the notifications, depending on the current mode. The shortcut menu also presents a Perform Example Transaction item, which will set the values of the component's StringProperty and CountProperty properties. You can undo the last designer transaction using the Undo command provided by the Visual Studio .NET development environment. */ namespace DesignerTransactionSample { // Associate the DTDesigner with this component [DesignerAttribute(typeof(DTDesigner))] public class DTComponent : System.ComponentModel.Component { private string m_String; private int m_Count; public string StringProperty { get { return m_String; } set { m_String = value; } } public int CountProperty { get { return m_Count; } set { m_Count = value; } } private void InitializeComponent() { m_String = "Initial Value"; m_Count = 0; } } internal class DTDesigner : ComponentDesigner { private bool notification_mode = false; private int count = 10; // The Verbs property is overridden from ComponentDesigner public override DesignerVerbCollection Verbs { get { DesignerVerbCollection dvc = new DesignerVerbCollection(); dvc.Add( new DesignerVerb("Perform Example Transaction", new EventHandler(this.DoTransaction)) ); if(notification_mode) dvc.Add(new DesignerVerb("End Designer Transaction Notifications", new EventHandler(this.UnlinkDTNotifications))); else dvc.Add(new DesignerVerb("Show Designer Transaction Notifications", new EventHandler(this.LinkDTNotifications))); return dvc; } } public override void Initialize(System.ComponentModel.IComponent component) { base.Initialize(component); IDesignerHost host = (IDesignerHost)GetService(typeof(IDesignerHost)); if(host == null) { MessageBox.Show("The IDesignerHost service interface could not be obtained."); return; } if( MessageBox.Show("Press the Yes button to display notification message boxes for the designer transaction opened and closed notifications.","Link DesignerTransaction Notifications?", MessageBoxButtons.YesNo, MessageBoxIcon.Question, MessageBoxDefaultButton.Button1, MessageBoxOptions.RightAlign) == DialogResult.Yes ) { host.TransactionOpened += new EventHandler(OnDesignerTransactionOpened); host.TransactionClosed += new DesignerTransactionCloseEventHandler(OnDesignerTransactionClosed); notification_mode = true; } } private void LinkDTNotifications(object sender, EventArgs e) { if(notification_mode == false) { IDesignerHost host = (IDesignerHost)GetService(typeof(IDesignerHost)); if(host != null) { notification_mode = true; host.TransactionOpened += new EventHandler(OnDesignerTransactionOpened); host.TransactionClosed += new DesignerTransactionCloseEventHandler(OnDesignerTransactionClosed); } } } private void UnlinkDTNotifications(object sender, EventArgs e) { if(notification_mode) { IDesignerHost host = (IDesignerHost)GetService(typeof(IDesignerHost)); if(host != null) { notification_mode = false; host.TransactionOpened -= new EventHandler(OnDesignerTransactionOpened); host.TransactionClosed -= new DesignerTransactionCloseEventHandler(OnDesignerTransactionClosed); } } } private void OnDesignerTransactionOpened(object sender, EventArgs e) { System.Windows.Forms.MessageBox.Show("A Designer Transaction was started. (TransactionOpened)"); } private void OnDesignerTransactionClosed(object sender, DesignerTransactionCloseEventArgs e) { System.Windows.Forms.MessageBox.Show("A Designer Transaction was completed. (TransactionClosed)"); } private void DoTransaction(object sender, EventArgs e) { IDesignerHost host = (IDesignerHost)GetService(typeof(IDesignerHost)); DesignerTransaction t = host.CreateTransaction("Change Text and Size"); /* The code within the using statement is considered to be a single transaction. When the user selects Undo, the system will undo everything executed in this code block. */ using (t) { if(notification_mode) System.Windows.Forms.MessageBox.Show("Entering a Designer-Initiated Designer Transaction"); // The .NET Framework automatically associates the TypeDescriptor with the correct component PropertyDescriptor someText = TypeDescriptor.GetProperties(Component)["StringProperty"]; someText.SetValue(Component, "This text was set by the designer for this component."); PropertyDescriptor anInteger = TypeDescriptor.GetProperties(Component)["CountProperty"]; anInteger.SetValue(Component, count); count++; // Complete the designer transaction. t.Commit(); if(notification_mode) System.Windows.Forms.MessageBox.Show("Designer-Initiated Designer Transaction Completed"); } } protected override void Dispose(bool disposing) { UnlinkDTNotifications(this, new EventArgs()); base.Dispose(disposing); } } } [C++] #using <mscorlib.dll> #using <system.dll> #using <system.design.dll> #using <system.windows.forms.dll> using namespace System; using namespace System::ComponentModel; using namespace System::ComponentModel::Design; using namespace System::Windows::Forms; using namespace System::Windows::Forms::Design; /* This sample demonstrates how to perform a series of actions in a designer transaction, how to change values of properties of a component from a designer, and how to complete transactions without being interrupted by other activities. To run this sample, add this code to a class library project and compile. Create a new Windows Forms project or load a form in the designer. Add a reference to the class library that was compiled in the first step. Right-click the Toolbox in design mode and click Customize Toolbox. Browse to the class library that was compiled in the first step and select OK until the DTComponent item appears in the Toolbox. Add an instance of this component to the form. When the component is created and added to the component tray for your design project, the Initialize method of the designer is called. This method displays a message box informing you that designer transaction event handlers will be registered unless you click Cancel. When you set properties in the properties window, each change will be encapsulated in a designer transaction, allowing the change to be undone later. When you right-click the component, the shortcut menu for the component is displayed. The designer constructs this menu according to whether designer transaction notifications are enabled, and offers the option of enabling or disabling the notifications, depending on the current mode. The shortcut menu also presents a Perform Example Transaction item, which will set the values of the component's StringProperty and CountProperty properties. You can undo the last designer transaction using the Undo command provided by the Visual Studio .NET development environment. */ namespace DesignerTransactionSample { private __gc class DTDesigner : public ComponentDesigner { private: bool notification_mode; int count; void LinkDTNotifications(Object* /*sender*/, EventArgs* /*e*/) { if(!notification_mode) { IDesignerHost* host = dynamic_cast<IDesignerHost*>(GetService(__typeof(IDesignerHost))); if(host != 0) { notification_mode = true; host->TransactionOpened += new EventHandler(this, &DTDesigner::OnDesignerTransactionOpened); host->TransactionClosed += new DesignerTransactionCloseEventHandler(this, &DTDesigner::OnDesignerTransactionClosed); } } } void UnlinkDTNotifications(Object* /*sender*/, EventArgs* /*e*/) { if(notification_mode) { IDesignerHost* host = dynamic_cast<IDesignerHost*>(GetService(__typeof(IDesignerHost))); if(host != 0) { notification_mode = false; host->TransactionOpened -= new EventHandler(this, &DTDesigner::OnDesignerTransactionOpened); host->TransactionClosed -= new DesignerTransactionCloseEventHandler(this, &DTDesigner::OnDesignerTransactionClosed); } } } void OnDesignerTransactionOpened(Object* /*sender*/, EventArgs* /*e*/) { MessageBox::Show(S"A Designer Transaction was started. (TransactionOpened)"); } void OnDesignerTransactionClosed(Object* /*sender*/, DesignerTransactionCloseEventArgs* /*e*/) { MessageBox::Show(S"A Designer Transaction was completed. (TransactionClosed)"); } void DoTransaction(Object* /*sender*/, EventArgs* /*e*/) { IDesignerHost* host = static_cast<IDesignerHost*>(GetService(__typeof(IDesignerHost))); DesignerTransaction* t = host->CreateTransaction(S"Change Text and Size"); /* The code within the using statement is considered to be a single transaction. When the user selects Undo, the system will undo everything executed in this code block. */ if(notification_mode) MessageBox::Show(S"Entering a Designer-Initiated Designer Transaction"); // The .NET Framework automatically associates the TypeDescriptor with the correct component PropertyDescriptor* someText = TypeDescriptor::GetProperties(Component)->Item[S"StringProperty"]; someText->SetValue(Component, S"This text was set by the designer for this component."); PropertyDescriptor* anInteger = TypeDescriptor::GetProperties(Component)->Item[S"CountProperty"]; anInteger->SetValue(Component, __box(count)); count++; // Complete the designer transaction. t->Commit(); if(notification_mode) MessageBox::Show(S"Designer-Initiated Designer Transaction Completed"); } public: // The Verbs property is overridden from ComponentDesigner __property DesignerVerbCollection* get_Verbs() { DesignerVerbCollection* dvc = new DesignerVerbCollection(); dvc->Add( new DesignerVerb(S"Perform Example Transaction", new EventHandler(this, &DTDesigner::DoTransaction)) ); if(notification_mode) dvc->Add(new DesignerVerb(S"End Designer Transaction Notifications", new EventHandler(this, &DTDesigner::UnlinkDTNotifications))); else dvc->Add(new DesignerVerb(S"Show Designer Transaction Notifications", new EventHandler(this, &DTDesigner::LinkDTNotifications))); return dvc; } void Initialize(IComponent* component) { ComponentDesigner::Initialize(component); notification_mode = false; count = 10; IDesignerHost* host = dynamic_cast<IDesignerHost*>(GetService(__typeof(IDesignerHost))); if(host == 0) { MessageBox::Show(S"The IDesignerHost service interface could not be obtained."); return; } if( MessageBox::Show(S"Press the Yes button to display notification message boxes for the designer transaction opened and closed notifications.", S"Link DesignerTransaction Notifications?", MessageBoxButtons::YesNo, MessageBoxIcon::Question, MessageBoxDefaultButton::Button1, MessageBoxOptions::RightAlign) == DialogResult::Yes ) { host->TransactionOpened += new EventHandler(this, &DTDesigner::OnDesignerTransactionOpened); host->TransactionClosed += new DesignerTransactionCloseEventHandler(this, &DTDesigner::OnDesignerTransactionClosed); notification_mode = true; } } protected: void Dispose(bool disposing) { UnlinkDTNotifications(this, new EventArgs()); ComponentDesigner::Dispose(disposing); } }; // Associate the DTDesigner with this component [DesignerAttribute(__typeof(DTDesigner))] public __gc class DTComponent : public System::ComponentModel::Component { private: String* m_String; int m_Count; void InitializeComponent() { m_String = S"Initial Value"; m_Count = 0; } public: __property String* get_StringProperty() { return m_String; } __property void set_StringProperty(String* value) { m_String = value; } __property int get_CountProperty() { return m_Count; } __property void set_CountProperty(int value) { m_Count = value; } }; }
[JScript] No example is available for JScript. To view a Visual Basic, C#, or C++ example, click the Language Filter button
in the upper-left corner of the page.
Requirements
Namespace: System.ComponentModel.Design
Platforms: Windows 98, Windows NT 4.0, Windows Millennium Edition, Windows 2000, Windows XP Home Edition, Windows XP Professional, Windows Server 2003 family
Assembly: System (in System.dll)
See Also
DesignerTransaction Members | System.ComponentModel.Design Namespace | IDesignerHost | IComponentChangeService | PropertyDescriptor