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: 

Unpin Command Binding - Ribbon vs Toggle

16 REPLIES 16
Reply
Message 1 of 17
Sean_Page
953 Views, 16 Replies

Unpin Command Binding - Ribbon vs Toggle

After a string of unfortunate events, I am trying to bind to the Unpin command to ask users are they sure they want to unpin the element. This is working great when I bind to the "ID_UNLOCK_ELEMENTS" command.

 

However, if the element is locked, and then a users toggles it with the visual "pin" in the view, the bound event does not fire.  So, I think looked and found that the Command Id for that was actually different. So, I check and it said that it allows binding as well, bound to it using the same method and event, however nothing fires when the toggle is clicked.

 

Anyone have any idea why it would be acting different?

 

startup:

AddCommandBindings(application, "ID_UNLOCK_ELEMENTS");
AddCommandBindings(application, "ID_PIN_CTRL_TOGGLE");

 

Method:

private void AddCommandBindings(UIControlledApplication application, string name)
		{
			RevitCommandId rCommandId = RevitCommandId.LookupCommandId(name);
			if(rCommandId.CanHaveBinding)
			{
				try
				{
					switch(name)
					{
						case "ID_UNLOCK_ELEMENTS":
							application.CreateAddInCommandBinding(rCommandId).Executed += new EventHandler<ExecutedEventArgs>(DisableCommand);
							break;
						case "ID_PIN_CTRL_TOGGLE":
							application.CreateAddInCommandBinding(rCommandId).Executed += new EventHandler<ExecutedEventArgs>(UnPinToggle);
							break;
						case "ID_INPLACE_COMPONENT":
							application.CreateAddInCommandBinding(rCommandId).Executed += new EventHandler<ExecutedEventArgs>(DisableCommand);
							break;
						case "ID_FILE_IMPORT":
							application.CreateAddInCommandBinding(rCommandId).Executed += new EventHandler<ExecutedEventArgs>(DisableCommand);
							break;
						case "ID_WORKSETS_RELOAD_LATEST":
							application.CreateAddInCommandBinding(rCommandId).Executed += new EventHandler<ExecutedEventArgs>(ReloadLatestUpdaters);
							break;
						default:
							break;
					}

				}
				catch
				{
					MessageBox.Show("Command " + name + " is already bound.");
				}
			}
		}

 

Event (Essentially just presents a dialog tot he user with the command info and why they shouldn't be doing what they are doing, general utility):

		private void DisableCommand(object sender, ExecutedEventArgs args)
		{
			using(Forms.RevitPostCommandForm rpc = new Forms.RevitPostCommandForm(args.CommandId))
			{
				if(rpc.ShowDialog() == DialogResult.OK)
				{
					ControlParams.postCommand = args.CommandId.Name;
					UIDocument uiDoc = new UIDocument(args.ActiveDocument);
					uiDoc.Application.RemoveAddInCommandBinding(args.CommandId);
					ControlParams.application.Idling += new EventHandler<IdlingEventArgs>(PostCommand_Idling);
					idleCheck = false;
					uiDoc.Application.PostCommand(args.CommandId);
				}
			}
		}
16 REPLIES 16
Message 2 of 17
ricaun
in reply to: Sean_Page

That's interesting... I create a test plugin to look at how this command binding works.
And I was not able to make the toggle binding work.


How did you get the ID_PIN_CTRL_TOGGLE name? I was trying to find the PostableCommand related to this lock/unlock toggle and it does not exist on the Revit API.

ID_PIN_CTRL_TOGGLE 	 34967	PostableCommand.????
ID_UNLOCK_ELEMENTS 	 33001	PostableCommand.Unpin

Maybe it's not possible to add the binding command on this toggle event.

 

Should an IUpdater with the BuiltInParameter.ELEMENT_LOCKED_PARAM works better, to prevent unlocking the elements.

Should be annoying to add on each type of element but should work.

Gonna make some tests...

Luiz Henrique Cassettari

ricaun.com - Revit API Developer

AppLoader EasyConduit WireInConduit ConduitMaterial CircuitName ElectricalUtils

Message 3 of 17
Sean_Page
in reply to: ricaun

Thanks @ricaun, I found that ID in the journal files. If you use the CanHaveBinding it says true, as does Has binding after, but it doesn't fire.

 

I also did look at using the locked param in an updated as that was my go-to, however using that param specifically as a param trigger doesn't work, but it does initiate the AnyChange trigger. So, I didn't want to try and use an any change and check for the param on all elements, or I'd like not to anyways.

 

And yes, it would also mean a lot of categories, which I'm not sure I'm keen on either for performance.

Message 4 of 17
Sean_Page
in reply to: Sean_Page

I also tried this with a category filter as well and neither worked for me.

Updaters.ElementUnpinUpdater PinnedUpdater = new Updaters.ElementUnpinUpdater(application.ActiveAddInId);
UpdaterRegistry.RegisterUpdater(PinnedUpdater, true);
ElementClassFilter wallFilter = new ElementClassFilter(typeof(Wall));				UpdaterRegistry.AddTrigger(PinnedUpdater.GetUpdaterId(), wallFilter, Element.GetChangeTypeParameter(new ElementId(BuiltInParameter.ELEMENT_LOCKED_PARAM)));

 

Message 5 of 17
ricaun
in reply to: Sean_Page

I'm not able to trigger the ELEMENT_LOCKED_PARAM parameter on the updater too.

 

I'm using the invert option to make all the category to trigger.

new ElementCategoryFilter(BuiltInCategory.INVALID, true);

And I tested with the ALL_MODEL_INSTANCE_COMMENTS and works fine.

Element.GetChangeTypeParameter(new ElementId(BuiltInParameter.ALL_MODEL_INSTANCE_COMMENTS))

The instance comments work fine but the locked parameter still does not trigger.

 

I also try to set the trigger on each valid BuiltInParameter.

var values = Enum.GetValues(typeof(BuiltInParameter)).Cast<BuiltInParameter>();
var changeTypes = values.Select(e => Element.GetChangeTypeParameter(new ElementId(e))).ToArray();

On the updater, I'm using the IsChangeTriggered to check each BuiltInParameter to find what makes the updater activate.

public void Execute(UpdaterData data)
{
    var document = data.GetDocument();
    var ids = new List<ElementId>();
    ids.AddRange(data.GetModifiedElementIds());
    var elements = ids.Select(id => document.GetElement(id));
    var values = Enum.GetValues(typeof(BuiltInParameter)).Cast<BuiltInParameter>();
    foreach (var element in elements)
    {
        Console.WriteLine($"{element.Id}");
        foreach (var value in values)
        {
            var isChange = data.IsChangeTriggered(element.Id, Element.GetChangeTypeParameter(new ElementId(value)));
            if (isChange)
                Console.WriteLine($"{element.Id} {value} {isChange}");
        }
    }
}

Works fine with all parameters I tested the only exception is the ELEMENT_LOCKED_PARAM parameter that does not trigger for some reason.

 

I tested on Revit 2018, 2021 and 2023 and nothing I tried makes the ELEMENT_LOCKED_PARAM updater to trigger.

 

Maybe is a bug...

 

 

Luiz Henrique Cassettari

ricaun.com - Revit API Developer

AppLoader EasyConduit WireInConduit ConduitMaterial CircuitName ElectricalUtils

Message 6 of 17
Sean_Page
in reply to: Sean_Page

@jeremytammik any chance we could get the Dev team to weigh in here?

Message 7 of 17
jeremy_tammik
in reply to: Sean_Page

Sure thing. I asked them whether they can take a look at this thread in its current state or whether I need to raise a ticket for them to analyse in more depth. Can you reformulate and reduce the issue to the bare minimal problem in a succinct form and possibly add a minimal reproducible case with step by step description for them to analyse, so they don't have to read and understand the entire discussion above? Thank you!

 

Jeremy Tammik Developer Advocacy and Support + The Building Coder + Autodesk Developer Network + ADN Open
Message 8 of 17
Sean_Page
in reply to: jeremy_tammik

I have attached a minimal reproducible case project.

 

This case includes two updaters both firing on walls to make it simple.

1. Updater 1 should be firing against the BuiltInParameter.ELEMENT_LOCKED_PARAM

    A. This does NOT work

2. Updater 2 should be firing against the BuiltInParameter.ALL_MODEL_MARK

    A. This DOES work

 

spage_0-1656417370636.png

 

spage_1-1656418089422.png

 

 

Message 9 of 17
RPTHOMAS108
in reply to: Sean_Page

Did you get the result you expect from below line of your code:

 

RevitCommandId rCommandId = RevitCommandId.LookupCommandId(name);

 

i.e. why wasn't the below used instead:

 

public static RevitCommandId LookupPostableCommandId(PostableCommand postableCommand)

 

Assuming you are going to need to post the command if user selects ok then the command needs to be both post-able and bind-able. Most things outside of the ribbon can't be posted.

 

I've not reviewed the updater approach yet, I would assume that should work but some parameter changes have been known not to trigger the updater. Not sure execute method of IUpdater should be used to interact with user however i.e. ask user what to do next (updater should know what to do and do it transparently).

 

You can post pin and unpin it seems but the state of the selected element should be found i.e. on the Ribbon it is a toggle but there are two separate post-able commands.

Message 10 of 17
Sean_Page
in reply to: RPTHOMAS108

Not exactly sure what you mean by "expected result" of my code. As shown, I am successfully using that to bind to several commands without any issue. This one states that is it bindable, and that the biding is happening, but then then doesn't do anything when the command is run.

 

The other event handlers are how I am proceeding with posting the actual command if user selects OK.

 

1. Bind to Command.

    A. Execution Event to Handle Command

    B. Idling Event within Execution to handle a "YES" response

3. Ask User "Are you Sure"

    A. If user says NO, then nothing happens

    B. If user says Yes

        1. Unbind Command

        2. Submit Command

       3. Idling Event to rebind after Command Executed normally

        3. Rebind Command with Event

 

I guess in short, my code works as intended (doesn't mean its the best :)) for other command bindings on a similar nature, and works as intended when the ribbon "Pin" is pressed, just not the Graphical UI pin within the view.

Message 11 of 17
RPTHOMAS108
in reply to: Sean_Page

Was wondering specifically if you got a command id back when you looked for it by name:

"ID_PIN_CTRL_TOGGLE"

Was the binding created?

 

Regardless it doesn't appear in post-able command enum so I wouldn't think you could post it even if it fires the command binding event. Although you could perhaps find the current state of the element(s) and post the pin/unpin on the main UI, or change parameter.

Message 12 of 17
Sean_Page
in reply to: RPTHOMAS108

Yes, I get Id that are different, and it states it can be bound.

 

spage_0-1656422956319.png

 

The Journal files are also showing that the binding is successful:

 

' 0:< API_SUCCESS { Replacing command id 'ID_UNLOCK_ELEMENTS' Executed implementation with implementation from application 'Testing' dll 'C:\ProgramData\Autodesk\Revit\Addins\2022\PinnedUpdater.dll'. }
' 0:< API_SUCCESS { API registering command Allow change of element position
'Unpin Executed event by application Testing (2b51409d-cb10-4a88-8a59-f94b6324847c). }
' 0:< API_SUCCESS { Replacing command id 'ID_PIN_CTRL_TOGGLE' Executed implementation with implementation from application 'Testing' dll 'C:\ProgramData\Autodesk\Revit\Addins\2022\PinnedUpdater.dll'. }
' 0:< API_SUCCESS { API registering command Prevent or allow change of element position
'Toggle Pin
'&Toggle Pin Executed event by application Testing (2b51409d-cb10-4a88-8a59-f94b6324847c). }

Message 13 of 17
ricaun
in reply to: Sean_Page

@Sean_Page and @jeremy_tammik

 

I gonna create a separate Topic related to the IUpdater problem. So this topic could focus on the Binding Command problem.

 

I create an application and test a lot of things and found some problems not only with the ELEMENT_LOCKED_PARAM not triggering.

 

Here is the application: https://github.com/ricaun-io/RevitAddin.UpdaterTester/

Luiz Henrique Cassettari

ricaun.com - Revit API Developer

AppLoader EasyConduit WireInConduit ConduitMaterial CircuitName ElectricalUtils

Message 14 of 17
jeremy_tammik
in reply to: ricaun

OK. Sorry to hear that there appear to be some issues in this area. Let's see what the development team say about this thread, and point out the new one and possibly raise a ticket with them once you have done some research and started a new separate thread for that. Thank you very much for that!

  

Jeremy Tammik Developer Advocacy and Support + The Building Coder + Autodesk Developer Network + ADN Open
Message 15 of 17
jeremy_tammik
in reply to: Sean_Page

The devteam confirmed some weirdness and are exploring further. Thank you very much for raising this!

  

Jeremy Tammik Developer Advocacy and Support + The Building Coder + Autodesk Developer Network + ADN Open
Message 16 of 17
ggranadosNFAMX
in reply to: Sean_Page

Hi all, is there any update to this issue, I have been testing a Hook code for "ID_PIN_CTRL_TOGGLE" Command Id, but nothing happens when the pin toggle is pressed.

Thank You!

Message 17 of 17
dgoff96
in reply to: ggranadosNFAMX

I'm also interested in a solution to this. I'm running into the same issue and I definitely think that designers use the graphic "Pin" toggle more than the ribbon button.

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

Post to forums  

Forma Design Contest


Rail Community