Revit API Forum
Welcome to Autodesk’s Revit API Forums. Share your knowledge, ask questions, and explore popular Revit API topics.
cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

postable command usage

44 REPLIES 44
SOLVED
Reply
Message 1 of 45
Ning_Zhou
3680 Views, 44 Replies

postable command usage

Ning_Zhou
Advocate
Advocate

seems postable command usage is quite limited, for instance

1) can only send warning message instead of disable command?

2) OOTB duplicate view will name that duplicated view w/ suffix Copy 1, is it possible to name it differently?

0 Likes

postable command usage

seems postable command usage is quite limited, for instance

1) can only send warning message instead of disable command?

2) OOTB duplicate view will name that duplicated view w/ suffix Copy 1, is it possible to name it differently?

44 REPLIES 44
Message 2 of 45
jeremytammik
in reply to: Ning_Zhou

jeremytammik
Autodesk
Autodesk

Regarding your question 2, you could react to the new view creation and rename it afterwards in an additional step, either using DMU or the document changed event.

 



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

0 Likes

Regarding your question 2, you could react to the new view creation and rename it afterwards in an additional step, either using DMU or the document changed event.

 



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

Message 3 of 45
Ning_Zhou
in reply to: jeremytammik

Ning_Zhou
Advocate
Advocate

right, i'll give it a try, thanks Jeremy!

by the way, don't know if i can use ElementTypeDuplicated Event? i assume view duplicating is instance based operation, isn't it?

0 Likes

right, i'll give it a try, thanks Jeremy!

by the way, don't know if i can use ElementTypeDuplicated Event? i assume view duplicating is instance based operation, isn't it?

Message 4 of 45
Sean_Page
in reply to: Ning_Zhou

Sean_Page
Collaborator
Collaborator

If you add Command Binding to the applicable Postable Commands you can indeed disable them by just making them do nothing, or giving the user a warning.

 

DMU is my preferred method to catch new views and rename them.

Sean Page, AIA, NCARB, LEED AP
Partner, Computational Designer, Architect
0 Likes

If you add Command Binding to the applicable Postable Commands you can indeed disable them by just making them do nothing, or giving the user a warning.

 

DMU is my preferred method to catch new views and rename them.

Sean Page, AIA, NCARB, LEED AP
Partner, Computational Designer, Architect
Message 5 of 45
Ning_Zhou
in reply to: Ning_Zhou

Ning_Zhou
Advocate
Advocate

i did a quick test using document changed event, seems i cannot start transaction in order to change view name, did i miss something?

 

public void AppDocumentChanged(object sender, Autodesk.Revit.DB.Events.DocumentChangedEventArgs args)
{

ICollection<ElementId> views = new FilteredElementCollector(doc).OfClass(typeof(View)).ToElementIds();

ICollection<ElementId> ids = args.GetAddedElementIds();
foreach (ElementId id in ids)
if (views.Contains(id))
{
Element e = doc.GetElement(id);
string name = Regex.Replace(e.Name, @" Copy 1", "_zn"); // name changed successfully
using (Transaction tx = new Transaction(doc))
{
tx.Start("renameTransaction");
try
{
e.Name = name;
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
tx.Commit();
}
}
}

0 Likes

i did a quick test using document changed event, seems i cannot start transaction in order to change view name, did i miss something?

 

public void AppDocumentChanged(object sender, Autodesk.Revit.DB.Events.DocumentChangedEventArgs args)
{

ICollection<ElementId> views = new FilteredElementCollector(doc).OfClass(typeof(View)).ToElementIds();

ICollection<ElementId> ids = args.GetAddedElementIds();
foreach (ElementId id in ids)
if (views.Contains(id))
{
Element e = doc.GetElement(id);
string name = Regex.Replace(e.Name, @" Copy 1", "_zn"); // name changed successfully
using (Transaction tx = new Transaction(doc))
{
tx.Start("renameTransaction");
try
{
e.Name = name;
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
tx.Commit();
}
}
}

Message 6 of 45
Sean_Page
in reply to: Ning_Zhou

Sean_Page
Collaborator
Collaborator

I do not believe you can produce a Transaction during this event. It is a read only event according to the docs.

 

https://www.revitapidocs.com/2015/988dd6cf-fcaa-85d2-622d-c50f13917a13.htm

 

That is why DMU is so nice, it happens in a transaction already so no need to start another one.

 

Sean Page, AIA, NCARB, LEED AP
Partner, Computational Designer, Architect
0 Likes

I do not believe you can produce a Transaction during this event. It is a read only event according to the docs.

 

https://www.revitapidocs.com/2015/988dd6cf-fcaa-85d2-622d-c50f13917a13.htm

 

That is why DMU is so nice, it happens in a transaction already so no need to start another one.

 

Sean Page, AIA, NCARB, LEED AP
Partner, Computational Designer, Architect
Message 7 of 45
Sean_Page
in reply to: Ning_Zhou

Sean_Page
Collaborator
Collaborator

Also, are you missing { } on your foreach?

Sean Page, AIA, NCARB, LEED AP
Partner, Computational Designer, Architect
0 Likes

Also, are you missing { } on your foreach?

Sean Page, AIA, NCARB, LEED AP
Partner, Computational Designer, Architect
Message 8 of 45
Ning_Zhou
in reply to: Sean_Page

Ning_Zhou
Advocate
Advocate

thanks spage, can you elaborate on Command Binding thing to disable / give warning? yes, i'll try DMU later as suggested by Jeremy too

0 Likes

thanks spage, can you elaborate on Command Binding thing to disable / give warning? yes, i'll try DMU later as suggested by Jeremy too

Message 9 of 45
Ning_Zhou
in reply to: Sean_Page

Ning_Zhou
Advocate
Advocate

good to know that document changed event is read only, perhaps factory should provide us w/ document changing event too?

i skipped {} as only one if statement here, well, not good practice, thanks again

0 Likes

good to know that document changed event is read only, perhaps factory should provide us w/ document changing event too?

i skipped {} as only one if statement here, well, not good practice, thanks again

Message 10 of 45
Sean_Page
in reply to: Ning_Zhou

Sean_Page
Collaborator
Collaborator

See here.

https://boostyourbim.wordpress.com/2013/01/14/how-to-override-commands-in-the-revit-ui-if-you-really...

Sean Page, AIA, NCARB, LEED AP
Partner, Computational Designer, Architect
0 Likes

See here.

https://boostyourbim.wordpress.com/2013/01/14/how-to-override-commands-in-the-revit-ui-if-you-really...

Sean Page, AIA, NCARB, LEED AP
Partner, Computational Designer, Architect
Message 11 of 45
Ning_Zhou
in reply to: Sean_Page

Ning_Zhou
Advocate
Advocate

thanks spage, works great! what if i want to give warning only and continue that command in OOTB way?

0 Likes

thanks spage, works great! what if i want to give warning only and continue that command in OOTB way?

Message 12 of 45
Sean_Page
in reply to: Ning_Zhou

Sean_Page
Collaborator
Collaborator

You would need to Remove the command binding after the warning and the use a PostCommand to call the initial CommandId.

 

You can also use Idle handlers to create the binding again if you want it to happen every time and not just the first time.

Sean Page, AIA, NCARB, LEED AP
Partner, Computational Designer, Architect
0 Likes

You would need to Remove the command binding after the warning and the use a PostCommand to call the initial CommandId.

 

You can also use Idle handlers to create the binding again if you want it to happen every time and not just the first time.

Sean Page, AIA, NCARB, LEED AP
Partner, Computational Designer, Architect
Message 13 of 45
Ning_Zhou
in reply to: Sean_Page

Ning_Zhou
Advocate
Advocate

right, i need to use idle stuff to make sure it works every time, thanks.

0 Likes

right, i need to use idle stuff to make sure it works every time, thanks.

Message 14 of 45
Ning_Zhou
in reply to: Sean_Page

Ning_Zhou
Advocate
Advocate

hi spage, for idle event, which scope should i put into, app or cmd? if i put @ app scope i.e. startup then it's one time only, if i put @ cmd scope then how can i use OOTB import command instead of addin command?

0 Likes

hi spage, for idle event, which scope should i put into, app or cmd? if i put @ app scope i.e. startup then it's one time only, if i put @ cmd scope then how can i use OOTB import command instead of addin command?

Message 15 of 45
Sean_Page
in reply to: Ning_Zhou

Sean_Page
Collaborator
Collaborator

So I have it in the Application level.

 

1. On Startup Biding and capturing the application for later use.

        public Result OnStartup(UIControlledApplication application)
        {
            ControlID.application = application;
            AddCommandBindings(application, "ID_INPLACE_COMPONENT");
            return Result.Succeeded;
        }

 

2. Add the Command Binding and the Method to call when it captures the command.

        private Result AddCommandBindings(UIControlledApplication application, string name)
        {
            RevitCommandId rCommandId = RevitCommandId.LookupCommandId(name);
            if (rCommandId.CanHaveBinding)
            {
                try
                {
                    if (name == "ID_INPLACE_COMPONENT")
                    {
                        application.CreateAddInCommandBinding(rCommandId).Executed += new EventHandler<ExecutedEventArgs>(this.DisableCommand);
                    }
                }
                catch
                {
                    MessageBox.Show("Command " + name + " is already bound.");
                }
            }
            return Result.Succeeded;
        }

 

3. This is the Method the CommandBinding calls when fired

private void DisableCommand(object sender, ExecutedEventArgs args)
        {
            ControlID.postCommand = args.CommandId.Name;
            using (Forms.RevitPostCommandForm rpc = new Forms.RevitPostCommandForm())
            {
                if (rpc.ShowDialog() == DialogResult.OK)
                {
                    UIDocument uiDoc = new UIDocument(args.ActiveDocument);
                    uiDoc.Application.RemoveAddInCommandBinding(args.CommandId);
                    uiDoc.Application.PostCommand(args.CommandId);
                    ControlID.application.Idling += new EventHandler<IdlingEventArgs>(InPlaceComponent_Idling);
                }
            }
        }

 

4. Use the associated idling event to Add the command binding back after it has fired the second time.

        private void InPlaceComponent_Idling(object sender, IdlingEventArgs args)
        {
            AddCommandBindings(ControlID.application, "ID_INPLACE_COMPONENT");
            ControlID.application.Idling -= InPlaceComponent_Idling;
        }

 

 public static class ControlID
        {
            public static UIControlledApplication application { get; set; }
         }

 

Sean Page, AIA, NCARB, LEED AP
Partner, Computational Designer, Architect
0 Likes

So I have it in the Application level.

 

1. On Startup Biding and capturing the application for later use.

        public Result OnStartup(UIControlledApplication application)
        {
            ControlID.application = application;
            AddCommandBindings(application, "ID_INPLACE_COMPONENT");
            return Result.Succeeded;
        }

 

2. Add the Command Binding and the Method to call when it captures the command.

        private Result AddCommandBindings(UIControlledApplication application, string name)
        {
            RevitCommandId rCommandId = RevitCommandId.LookupCommandId(name);
            if (rCommandId.CanHaveBinding)
            {
                try
                {
                    if (name == "ID_INPLACE_COMPONENT")
                    {
                        application.CreateAddInCommandBinding(rCommandId).Executed += new EventHandler<ExecutedEventArgs>(this.DisableCommand);
                    }
                }
                catch
                {
                    MessageBox.Show("Command " + name + " is already bound.");
                }
            }
            return Result.Succeeded;
        }

 

3. This is the Method the CommandBinding calls when fired

private void DisableCommand(object sender, ExecutedEventArgs args)
        {
            ControlID.postCommand = args.CommandId.Name;
            using (Forms.RevitPostCommandForm rpc = new Forms.RevitPostCommandForm())
            {
                if (rpc.ShowDialog() == DialogResult.OK)
                {
                    UIDocument uiDoc = new UIDocument(args.ActiveDocument);
                    uiDoc.Application.RemoveAddInCommandBinding(args.CommandId);
                    uiDoc.Application.PostCommand(args.CommandId);
                    ControlID.application.Idling += new EventHandler<IdlingEventArgs>(InPlaceComponent_Idling);
                }
            }
        }

 

4. Use the associated idling event to Add the command binding back after it has fired the second time.

        private void InPlaceComponent_Idling(object sender, IdlingEventArgs args)
        {
            AddCommandBindings(ControlID.application, "ID_INPLACE_COMPONENT");
            ControlID.application.Idling -= InPlaceComponent_Idling;
        }

 

 public static class ControlID
        {
            public static UIControlledApplication application { get; set; }
         }

 

Sean Page, AIA, NCARB, LEED AP
Partner, Computational Designer, Architect
Message 16 of 45
Ning_Zhou
in reply to: Sean_Page

Ning_Zhou
Advocate
Advocate

thanks spage, works great! except that i have to click OK twice, means that DisableCommand being executed twice, i assume it cannot be avoided because that same command being posted again, perhaps if i missed something?

0 Likes

thanks spage, works great! except that i have to click OK twice, means that DisableCommand being executed twice, i assume it cannot be avoided because that same command being posted again, perhaps if i missed something?

Message 17 of 45
Sean_Page
in reply to: Ning_Zhou

Sean_Page
Collaborator
Collaborator

I am not somewhere I can test, but I think the Postcommand is queued until after all the other code runs, which means the Idling event is actually firing first. Maybe a Thread.Sleep(2000) in the Idling will give the PostCommand a chance to fire. Not positive on that.

Sean Page, AIA, NCARB, LEED AP
Partner, Computational Designer, Architect
0 Likes

I am not somewhere I can test, but I think the Postcommand is queued until after all the other code runs, which means the Idling event is actually firing first. Maybe a Thread.Sleep(2000) in the Idling will give the PostCommand a chance to fire. Not positive on that.

Sean Page, AIA, NCARB, LEED AP
Partner, Computational Designer, Architect
Message 18 of 45
Ning_Zhou
in reply to: Sean_Page

Ning_Zhou
Advocate
Advocate

i did quick test, no, doesn't work, just delayed.

0 Likes

i did quick test, no, doesn't work, just delayed.

Message 19 of 45
Sean_Page
in reply to: Ning_Zhou

Sean_Page
Collaborator
Collaborator

Looking back at my code which is working for me, the only thing I see is that I have the idler handler BEFORE the post command. 

 

private void DisableCommand(object sender, ExecutedEventArgs args)
        {
            ControlID.postCommand = args.CommandId.Name;
            using (Forms.RevitPostCommandForm rpc = new Forms.RevitPostCommandForm())
            {
                if (rpc.ShowDialog() == DialogResult.OK)
                {
                    UIDocument uiDoc = new UIDocument(args.ActiveDocument);
                    uiDoc.Application.RemoveAddInCommandBinding(args.CommandId);
                    ControlID.application.Idling += new EventHandler<IdlingEventArgs>(InPlaceComponent_Idling);
                    uiDoc.Application.PostCommand(args.CommandId);
                }
            }
        }

  

Sean Page, AIA, NCARB, LEED AP
Partner, Computational Designer, Architect
0 Likes

Looking back at my code which is working for me, the only thing I see is that I have the idler handler BEFORE the post command. 

 

private void DisableCommand(object sender, ExecutedEventArgs args)
        {
            ControlID.postCommand = args.CommandId.Name;
            using (Forms.RevitPostCommandForm rpc = new Forms.RevitPostCommandForm())
            {
                if (rpc.ShowDialog() == DialogResult.OK)
                {
                    UIDocument uiDoc = new UIDocument(args.ActiveDocument);
                    uiDoc.Application.RemoveAddInCommandBinding(args.CommandId);
                    ControlID.application.Idling += new EventHandler<IdlingEventArgs>(InPlaceComponent_Idling);
                    uiDoc.Application.PostCommand(args.CommandId);
                }
            }
        }

  

Sean Page, AIA, NCARB, LEED AP
Partner, Computational Designer, Architect
Message 20 of 45
Ning_Zhou
in reply to: Sean_Page

Ning_Zhou
Advocate
Advocate

thanks spage, still doesn't work, the only difference is that i used window message box

DialogResult result = MessageBox.Show("click OK to continue importing but your action will be logged", "BIM & DD", MessageBoxButtons.OKCancel);
if (result == DialogResult.OK)
{
uiApp.RemoveAddInCommandBinding(arg.CommandId);
uiApp.Idling += new EventHandler<IdlingEventArgs>(OnIdling);
uiApp.PostCommand(arg.CommandId);
}

0 Likes

thanks spage, still doesn't work, the only difference is that i used window message box

DialogResult result = MessageBox.Show("click OK to continue importing but your action will be logged", "BIM & DD", MessageBoxButtons.OKCancel);
if (result == DialogResult.OK)
{
uiApp.RemoveAddInCommandBinding(arg.CommandId);
uiApp.Idling += new EventHandler<IdlingEventArgs>(OnIdling);
uiApp.PostCommand(arg.CommandId);
}

Can't find what you're looking for? Ask the community or share your knowledge.

Post to forums  

Autodesk Design & Make Report