Multiple methods in a single command

Multiple methods in a single command

jelliottCRA
Contributor Contributor
1,797 Views
5 Replies
Message 1 of 6

Multiple methods in a single command

jelliottCRA
Contributor
Contributor

Hello,

I have a working autosync plugin that currently has no interface. I'd like to add (to start) an on/off button to my custom ribbon that will modify the xml config file for the autosync plugin. However, I'm stuck because I'm not sure whether I can add a second method to my autosync command that is called ToggleSync -- this would just modify a parameter in the config file that is read by the other method.  When I attempt to run the command, I get this error (see below). 

 

I understand that I could create a separate command where the toggle is the only method, but can I do that and still read/write the config file from the two places?

 

Thank you for your help!

 

error.PNG

0 Likes
Accepted solutions (1)
1,798 Views
5 Replies
Replies (5)
Message 2 of 6

mastjaso
Advocate
Advocate

I'm having a little bit of difficulty understanding what you're trying to describe, it would be easier if you shared the code that you were talking about.

 

But I think you're just trying to have multiple buttons? If that's the case the general flow is that you have:

 

1. a class that implements IExternalApplication (i.e. has OnStartup, and OnShutdown methods). In your OnStartup method, you would add your ribbon buttons, and associate each one with a different class that implements IExternalCommand.

 

2. A different class that implements IExternalCommand (i.e. has an Execute method), for each button. When someone clicks on a ribbon button, it looks for that class and runs the Execute method.

 

3. Each of these Execute methods is passed some information about the current context (current active revit model, etc.) and you can choose to use this if you want. If you're just trying to edit an XML file you can ignore that context, and regardless you'd put the code for editing that XML file in there, or atleast call the code that does the XML editing from there.

Example Manifest:

<?xml version="1.0" encoding="utf-8" standalone="no"?>
<RevitAddIns>
  <AddIn Type="Application">
    <Name>AddinTemplate</Name>
<!-- Assumes your .dll isn't in the top level Addins folder but
is in a sub folder called DefaultProjectNameFiles --> <Assembly>DefaultProjectNameFiles/DefaultProjectName.dll</Assembly> <AddInId> [GUID Goes Here] </AddInId> <FullClassName>RibbonButtons</FullClassName> <VendorId>MyComp</VendorId> <VendorDescription>MyComp</VendorDescription> </AddIn> </RevitAddIns>

Then in your DefaultProjectName project, you'd have a file with a class called "RibbonButtons" that adds your ribbon buttons:

 

namespace DefaultProjectName.App.RevitApp
{
    public class RibbonButtons : IExternalApplication
    {     

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

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

        static void AddRibbonButtons(UIControlledApplication application)
        {
            string TabName = "My_TAB";

            try
            {
                // Try to create a new tab.
                application.CreateRibbonTab(TabName);
            }
            catch
            {
                // The tab already exists, so we don't need to create it, we'll just add to it.
            }

            RibbonPanel panel = application.CreateRibbonPanel(TabName, "MyProjectPanel");

            string thisAssemblyPath = Assembly.GetExecutingAssembly().Location;
            // Create the main button.
            string title = "BigMainButton" + Environment.NewLine + "The Sequel";
            PushButtonData pbd = new PushButtonData("BigMainButtonUniqueID", title, thisAssemblyPath, "DefaultProjectName.App.RevitApp.ToggleAutoSync");
            PushButton pb = panel.AddItem(pbd) as PushButton;
            //if you want to add an image do the below 2 lines, set your image to be 64x64 pixels, png, and set the build action to "Resource".
            BitmapImage pbImage = new BitmapImage(new Uri("pack://application:,,,/DefaultProjectName;component/Resources/Checklist_6464.png"));
            pb.LargeImage = pbImage;
        }
    }
}

And then finally, you would have a your ToggleAutoSync class:

namespace DefaultProjectName.App.RevitApp
{
    public class ToggleAutoSync : IExternalCommand
    {
     public Result Execute(ExternalCommandData commandData, ref string message, ElementSet elements)
          {
          //do xml stuff here, e.g.:
MyStaticXMLWorker.ToggleFile(@"C:\testFile.xml"); } } }

So if you wanted to have multiple buttons, doing different things, you'd create multiple classes that implement ExternalCommand, and then create multiple ribbons buttons.

0 Likes
Message 3 of 6

jeremytammik
Autodesk
Autodesk

I have no idea what you are talking about either.

 

Before providing code even, a sentence or two describing the exact goal and the context might be more helpful still.

 



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

0 Likes
Message 4 of 6

jelliottCRA
Contributor
Contributor

I apologize for the terrible wording of that post, I was very lost but I think I have some clarity now. I was thinking I needed to have only one command class per application and needed to combine commands into a single class somehow. I now realize that is totally wrong and now reference two separate commands in order to have two buttons.

 

At a high level, I have a functioning autosync plugin that currently has no user-configurable options and no interface. It just syncs every 40 minutes once the application.idling event is registered. I was looking to create two commands: one that enables or disables the autosync, and one that allows the user to set a preferred sync interval. I have now created the form for data input and am working on using that data to modify the application's config file. Does this approach seem like a good one? 

 

Again, sorry for the confusion -- I am definitely new to the Revit API and C# in general. I appreciate the help!

0 Likes
Message 5 of 6

jeremytammik
Autodesk
Autodesk
Accepted solution

Yes, that makes total sense!

 

I implemented a little add-in that provides one single main command plus a secondary interactive settings command and stores its data in a config file. You could probably use lots of bits and pieces from that... which one was it? I think RvtFader:

 

 

Check out the implementation of its settings command.

 

Cheers,

 

Jeremy

 

 

 



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

Message 6 of 6

jelliottCRA
Contributor
Contributor

That does look like it has a lot of pieces that I can use. Thank you! I should definitely be able to get the last piece up and running now.

0 Likes