Modify properties and undo changes at design time with DesignerTransaction
The System.ComponentModel.Design.DesignerTransaction provides a
mechanism for enabling changes at design-time to be undone. This allows for
performance improvements, since most components defer processing until a
transaction has been opened and closed.
The following steps must be used in order to successfully open and close a
transaction.
-
Call IDesignerHost.CreateTransaction, which returns a DesignerTransaction
for transaction control.
-
Within a try block, make the changes to your object for each
action you want to track.
(a) Call OnComponentChanging to signal that the component is
about to be changed.
(b) Make the changes to the component.
(c) Call OnComponentChanged
to signal that the component has changed.
-
Within a finally block, call Commit
Note: When using PropertyDescriptor.SetValue, it
is not necessary to create a transaction, as the method automatically creates
the transaction, raises the change events, and commits the change.
Example:
private void AddPage(object sender, EventArgs e)
{
// Using a while (true) loop prevents long nested if-statements.
while (true)
{
IDesignerHost host = GetService(typeof(IDesignerHost)) as IDesignerHost;
if (host == null)
break;
PropertyDescriptor pd = TypeDescriptor.GetProperties(typeof(WizardView)["InteriorWizardPages"]);
if (pd == null)
break;
IDesignerTransaction trx = null;
try
{
try
{
// Create the transaction and signal that a property is about to be changed.
trx = host.CreateTransaction(Component.Site.Name+"AddPage");
RaiseComponentChanging(pd);
}
// Make sure the code file can be checked out if under source control.
catch (CheckOutException ex)
{
if (ex == CheckOutException.Canceled)
trx.Cancel();
}
// Let the host create the component so that it will be serialized.
// Then signal that the property has been changed.
InteriorWizardPage page = (InteriorWizardPage) host.CreateComponent(typeof(InteriorWizardPage));
this.WizardView.InteriorWizardPages.Add(page);
RaiseComponentChanged(pd, null, null);
}
finally
{
// Commit the transaction
trx.Commit();
}
// Always break at the end of the while loop
break;
}
}
In the code above, we create a transaction in order to modify a component.
During this time, Visual Studio .NET automatically tries to check out any
related source files. If for some reason a checkout fails, a CheckoutException
will be thrown, which we catch. We test the CheckoutException instance for the
static CheckoutException.Canceled instance; if they are equal, we cancel the
transaction. Any changes made to the component afterwards will not be saved.
Even committing a transaction after it was canceled will have no effect. If the
checkout was not canceled, or if some other instance of the CheckoutException
was caught, we do not cancel the transaction. The Commit method will then work
as expected.
Back to Tips and Tricks