Skip to content

StandardEditCommands and Instancing

Gary edited this page Aug 27, 2014 · 1 revision

Table of Contents

The Instancing Framework's component is StandardEditCommands (in the Sce.Atf.Applications namespace), which provides editing commands. StandardEditCommands implements the standard Edit menu's Cut, Copy, Paste, and Delete commands.

StandardEditCommands also provides edit commands on a context menu. For details on how it does this, see Using Context Menus.

To use StandardEditCommands in an application, simply include it in the MEF TypeCatalog. Create a class that implements IInstancingContext. When this class's context is active, StandardEditCommands automatically calls the IInstancingContext editing methods in response to menu item selections.

Executing Commands

StandardEditCommands is a command client and uses the ICommandClient interface to execute commands in the IInstancingContext interface. For information on ICommandClient, see Commands in ATF and Creating Command Clients in particular.

ICommandClient.CanDoCommand Implementation

Observing the ICommandClient implementation illustrates the process. First, the "Cut" case from CanDoCommand():

bool ICommandClient.CanDoCommand(object commandTag)
{
    bool canDo = false;

    IInstancingContext instancingContext = m_contextRegistry.GetActiveContext<IInstancingContext>();
    switch ((StandardCommand)commandTag)
    {
        case StandardCommand.EditCut:
            canDo =
                instancingContext != null &&
                instancingContext.CanCopy() &&
                instancingContext.CanDelete();
            break;
        ...

CanDoCommand() uses the ContextRegistry to get the current context to determine whether that context supports editing or not. The current context must implement IInstancingContext for edit commands to be executed. For the "Cut" command case shown, when instancingContext is non-null, instancingContext is used to invoke its IInstancingContext.CanCopy() and IInstancingContext.CanDelete() methods. Both these methods must return true to be able to perform a cut operation. The other editing commands in ICommandClient.CanDoCommand() are similar to "Cut".

ICommandClient.DoCommand Implementation

Next, look at the "Cut" case in ICommandClient.DoCommand():

void ICommandClient.DoCommand(object commandTag)
{
    switch ((StandardCommand)commandTag)
    {
        case StandardCommand.EditCut:
            Cut();
            break;
        ...

The StandardEditCommands.Cut() method does a copy and delete:

public void Cut()
{
    Copy();
    Delete("Cut".Localize("Cut the selection"));
}

Next, examine these copy and delete operations.

Copy Operation

StandardEditCommands.Copy() calls IInstancingContext.CanCopy() and IInstancingContext.Copy():

public void Copy()
{
    IInstancingContext instancingContext = m_contextRegistry.GetActiveContext<IInstancingContext>();
    if (instancingContext != null &&
        instancingContext.CanCopy())
    {
        object rawObject = instancingContext.Copy();
        IDataObject dataObject = rawObject as IDataObject ?? new DataObject(rawObject);

        OnCopying(EventArgs.Empty);

        Clipboard = dataObject;

        OnCopied(EventArgs.Empty);
    }
}

StandardEditCommands.Copy() gets the IInstancingContext instance as before, and after verifying it's non-null, invokes IInstancingContext.CanCopy() and IInstancingContext.Copy(). It casts the returned data as a System.Windows.Forms.IDataObject object, which allows copying the data to the Windows® clipboard. StandardEditCommands.Copy() also raises the StandardEditCommands.Copying and StandardEditCommandsCopied events at the appropriate times.

Delete Operation

The StandardEditCommands.Delete() method is similar, calling IInstancingContext.CanDelete() and IInstancingContext.Delete(). However, it has one key difference: it does the deletion in a transaction using ITransactionContext:

private void Delete(string commandName)
{
    OnDeleting(EventArgs.Empty);

    IInstancingContext instancingContext = m_contextRegistry.GetActiveContext<IInstancingContext>();
    if (instancingContext != null &&
        instancingContext.CanDelete())
    {
        ITransactionContext transactionContext = instancingContext.As<ITransactionContext>();
        transactionContext.DoTransaction(
            delegate
            {
                instancingContext.Delete();

                ISelectionContext selectionContext = instancingContext.As<ISelectionContext>();
                if (selectionContext != null)
                    selectionContext.Clear();
            }, commandName);
    }

    OnDeleted(EventArgs.Empty);
}

In addition to adapting the current context to IInstancingContext, it also adapts it to ITransactionContext. This means that the context has to implement ITransactionContext or the operation fails. The IInstancingContext.Delete() call occurs inside the transaction.

The current context is also cast as a ISelectionContext, so it must implement ISelectionContext as well. The ISelectionContext.Clear() call also occurs inside the transaction. StandardEditCommands.Delete() also raises the StandardEditCommands.Deleting and StandardEditCommands.Deleted events outside the transaction, before and after the deletion.

The other editing cases in ICommandClient.DoCommand() are similar to the "Cut" case in their use of IInstancingContext methods. StandardEditCommands.Paste() also employs a transaction.

Topics in this section

Clone this wiki locally