Delete confirmation

Delete confirmation

Shai.Nguyen
Advocate Advocate
1,369 Views
6 Replies
Message 1 of 7

Delete confirmation

Shai.Nguyen
Advocate
Advocate

Hi all,
I have a question. Is this possible to create a Confirmation when call "Delete" command?

public Result OnStartup(UIControlledApplication application)
        {
            RevitCommandId DeleteCommandId = RevitCommandId.LookupPostableCommandId(PostableCommand.Delete);
            AddInCommandBinding commandBinding = application.CreateAddInCommandBinding(DeleteCommandId);
                    commandBinding.Executed += AskWhenDelete;

            return Result.Succeeded;
        }

And here is my event:

private void AskWhenDelete(object sender, ExecutedEventArgs args)
        {
            TaskDialog taskDialog = new TaskDialog("Delete");
            taskDialog.MainContent = "Are you sure you want to delete?";
            TaskDialogCommonButtons buttons = TaskDialogCommonButtons.Ok | TaskDialogCommonButtons.Cancel;
            taskDialog.CommonButtons = buttons;

            if (TaskDialogResult.Ok == taskDialog.Show())
            {
                //what i have to code here?
            }
        }

Thanks in advanced.

 

0 Likes
Accepted solutions (1)
1,370 Views
6 Replies
Replies (6)
Message 2 of 7

jeremytammik
Autodesk
Autodesk

Maybe you can simply use PostCommand to launch the standard built-in Revit delete command at that point:

 

http://thebuildingcoder.typepad.com/blog/about-the-author.html#5.3

 

The built-in command will be launched and execute as soon as your command ends.

 

Please confirm that this works. It would make a nice little blog post sample.

 

Thank you!

 

Cheers,

 

Jeremy



Jeremy Tammik
Developer Technical Services
Autodesk Developer Network, ADN Open
The Building Coder

0 Likes
Message 3 of 7

Shai.Nguyen
Advocate
Advocate

Hi Jeremy,

My full code is:

public Result OnStartup(UIControlledApplication application)
        {
            RevitCommandId DeleteCommandId = RevitCommandId.LookupPostableCommandId(PostableCommand.Delete);
            AddInCommandBinding commandBinding = application.CreateAddInCommandBinding(DeleteCommandId);
                    commandBinding.Executed += AskWhenDelete;

            return Result.Succeeded;
        }
public Result OnShutdown(UIControlledApplication application)
        {

            return Result.Succeeded;
            
        }
private void AskWhenDelete(object sender, ExecutedEventArgs args)
        {            
            TaskDialog taskDialog = new TaskDialog("Delete");
            taskDialog.MainContent = "Are you sure you want to delete?";
            TaskDialogCommonButtons buttons = TaskDialogCommonButtons.Ok | TaskDialogCommonButtons.Cancel;
            taskDialog.CommonButtons = buttons;

            if (TaskDialogResult.Ok == taskDialog.Show())
            {
                RevitCommandId commandId = RevitCommandId.LookupPostableCommandId(PostableCommand.Delete);
                uiapp.PostCommand(commandId);
            }
            else
            {
                TaskDialog.Show("RV", "Cancel");
            }
        }

I tried to call UIApplication uiapp = commandData.Application but It's impossible. I'm stucked here. Please help. Thanks.

0 Likes
Message 4 of 7

RPTHOMAS108
Mentor
Mentor
Accepted solution

The problem you have is that once you add the handler for the executed event of the binding your code takes ownership of that command. This means that the question would be put to the user repeatedly (if you posted the same command ID as the one you are overriding). Note also that the command binding 'Delete' relates to the X button on the modify panel. There are other ways of deleting things that will not be captured, such as with right click delete in project browser.

 

You could try to remove the command binding but then after the post command completes you can not reattach it, you are out of context.

 

Some commands can be cancelled by setting the event arguments property 'cancel' to true but delete doesn't fall into this category it seems.

 

I believe this awkward design pattern exists because they expect you to provide your own full implementation of the command rather than intercepting the command and preventing it under certain circumstances. Would be good if there was a PostOriginalCommand function so you could always revert to the original built in command at the end of your command.

 

Implementing you own delete command is quite straightforward so you could do instead:

 

using System;
using Autodesk.Revit.DB;
using Autodesk.Revit.UI;

[Autodesk.Revit.Attributes.Transaction(Autodesk.Revit.Attributes.TransactionMode.Manual)]
[Autodesk.Revit.Attributes.Regeneration(Autodesk.Revit.Attributes.RegenerationOption.Manual)]
public class EntryAppClass : IExternalApplication
{

    private AddInCommandBinding DeleteCMDBinding = null;
    private bool Cancel = false;
    private void CheckDeleteFirst(object s, Autodesk.Revit.UI.Events.BeforeExecutedEventArgs e)
    {
        Cancel = false;
        if (TaskDialog.Show("Confirm delete", "Are you sure you want to delete?", TaskDialogCommonButtons.Yes | TaskDialogCommonButtons.No) == TaskDialogResult.No)
        {
            Cancel = true;
        }
    }
    private void CancelDelete(object s, Autodesk.Revit.UI.Events.ExecutedEventArgs e)
    {
        if (Cancel)
        {
            //Nothing to do
        }
        else
        {
            UIApplication UIApp = s as UIApplication;
            Document D = UIApp.ActiveUIDocument.Document;
            using (Transaction Tx = new Transaction(D, "Delete after check"))
            {
                if (Tx.Start() == TransactionStatus.Started)
                {
                    D.Delete(UIApp.ActiveUIDocument.Selection.GetElementIds());
                    Tx.Commit();
                }
            }
        }
    }

    private void ToggleAddinCMDBinding(UIControlledApplication App, bool OnShutDown = false)
    {
        try
        {
            if (DeleteCMDBinding == null == false)
            {
                DeleteCMDBinding.BeforeExecuted -= CheckDeleteFirst;
                DeleteCMDBinding.Executed -= CancelDelete;
                App.RemoveAddInCommandBinding(RevitCommandId.LookupPostableCommandId(PostableCommand.Delete));
                DeleteCMDBinding = null;
            }
            else
            {
                if (OnShutDown == false)
                {
                    DeleteCMDBinding = App.CreateAddInCommandBinding(RevitCommandId.LookupPostableCommandId(PostableCommand.Delete));
                    DeleteCMDBinding.BeforeExecuted += CheckDeleteFirst;
                    DeleteCMDBinding.Executed += CancelDelete;
                }
            }
        }
        catch (Exception ex)
        {
            //if command already bound this will fail
        }
    }

    public Result OnShutdown(Autodesk.Revit.UI.UIControlledApplication application)
    {
        ToggleAddinCMDBinding(application, true);
        return Autodesk.Revit.UI.Result.Succeeded;
    }
    public Result OnStartup(Autodesk.Revit.UI.UIControlledApplication application)
    {
        ToggleAddinCMDBinding(application);
        return Autodesk.Revit.UI.Result.Succeeded;
    }

}
0 Likes
Message 5 of 7

Shai.Nguyen
Advocate
Advocate

Thank you Thomas. I'm very appriciated!

0 Likes
Message 6 of 7

FAIR59
Advisor
Advisor

The most reliable method is to "catch" the transaction and cancel if needed. To catch the transaction subscribe to the UIControlledApplication.ControlledApplication.FailuresProcessing event.

 

In the event handler check for the transaction name "Delete Selection".

 

       public Autodesk.Revit.UI.Result OnStartup(UIControlledApplication application)
        {
            application.ControlledApplication.FailuresProcessing += ControlledApplication_FailuresProcessing;

 }

        void ControlledApplication_FailuresProcessing(object sender, Autodesk.Revit.DB.Events.FailuresProcessingEventArgs e)
        {
            FailuresAccessor fa = e.GetFailuresAccessor();
            if (fa.GetTransactionName().Equals("Delete Selection"))
            {
                TaskDialog td = new TaskDialog("confirm deletion");
                td.MainInstruction = "delete elements ?";
                td.CommonButtons = TaskDialogCommonButtons.Yes | TaskDialogCommonButtons.No;
                if (td.Show() != TaskDialogResult.Yes)
                {
                    e.SetProcessingResult(FailureProcessingResult.ProceedWithRollBack);
                }
            }
        }

 

0 Likes
Message 7 of 7

RPTHOMAS108
Mentor
Mentor

Probably dependant on product language.

0 Likes