{"id":2727,"date":"2024-09-04T08:43:44","date_gmt":"2024-09-04T08:43:44","guid":{"rendered":"https:\/\/infralligence.com\/?p=2727"},"modified":"2024-12-31T09:30:01","modified_gmt":"2024-12-31T09:30:01","slug":"buttons-in-revit-api-pushbutton-pulldownbutton-splitbutton-radiobuttongroup","status":"publish","type":"post","link":"https:\/\/infralligence.com\/pl\/resources\/buttons-in-revit-api-pushbutton-pulldownbutton-splitbutton-radiobuttongroup\/","title":{"rendered":"Buttons in Revit API: PushButton, PulldownButton, SplitButton, RadioButtonGroup"},"content":{"rendered":"<div data-elementor-type=\"wp-post\" data-elementor-id=\"2727\" class=\"elementor elementor-2727\">\n\t\t\t\t<div class=\"elementor-element elementor-element-a636728 e-con-full kk-blog-post e-flex rael-particle-no e-con e-parent\" data-id=\"a636728\" data-element_type=\"container\" data-e-type=\"container\">\n\t\t\t\t<div class=\"elementor-element elementor-element-978bece elementor-widget elementor-widget-text-editor\" data-id=\"978bece\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t\t<p>Revit API offers several types of buttons to enhance your plugin\u2019s UI: PushButton (most common), PulldownButton, SplitButton, and RadioButtonGroup.<\/p>\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-acc30ef elementor-widget elementor-widget-image\" data-id=\"acc30ef\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"image.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<img fetchpriority=\"high\" decoding=\"async\" width=\"2560\" height=\"1440\" src=\"https:\/\/infralligence.com\/wp-content\/uploads\/2024\/12\/c1033987-201e-4d07-bb17-4e16a2eea21d.png\" class=\"attachment-full size-full wp-image-2729\" alt=\"\" srcset=\"https:\/\/infralligence.com\/wp-content\/uploads\/2024\/12\/c1033987-201e-4d07-bb17-4e16a2eea21d.png 2560w, https:\/\/infralligence.com\/wp-content\/uploads\/2024\/12\/c1033987-201e-4d07-bb17-4e16a2eea21d-300x169.png 300w, https:\/\/infralligence.com\/wp-content\/uploads\/2024\/12\/c1033987-201e-4d07-bb17-4e16a2eea21d-1024x576.png 1024w, https:\/\/infralligence.com\/wp-content\/uploads\/2024\/12\/c1033987-201e-4d07-bb17-4e16a2eea21d-768x432.png 768w, https:\/\/infralligence.com\/wp-content\/uploads\/2024\/12\/c1033987-201e-4d07-bb17-4e16a2eea21d-1536x864.png 1536w, https:\/\/infralligence.com\/wp-content\/uploads\/2024\/12\/c1033987-201e-4d07-bb17-4e16a2eea21d-2048x1152.png 2048w\" sizes=\"(max-width: 2560px) 100vw, 2560px\" \/>\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-98d5948 elementor-widget elementor-widget-text-editor\" data-id=\"98d5948\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t\t<h5>\ud83d\udccc TLDR \u2013 Summary Upfront:<\/h5><p>\u27a1\ufe0f Use PushButtons for single commands.<\/p><p>\u27a1\ufe0f Use PulldownButtons and SplitButtons to group similar commands.<\/p><p>\u27a1\ufe0f Use RadioButtonGroups to let users set preferences.<\/p><p>Avoid repetitions in command classes: use C# inheritance and generics to create a parent abstract class and subclasses for specific Revit element types.<\/p>\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-ecaaabc elementor-widget elementor-widget-rael-table-of-contents\" data-id=\"ecaaabc\" data-element_type=\"widget\" data-e-type=\"widget\" data-settings=\"{&quot;rael_headings_by_tags&quot;:[&quot;h3&quot;,&quot;h4&quot;],&quot;rael_exclude_headings_by_selector&quot;:[],&quot;rael_min_height&quot;:{&quot;unit&quot;:&quot;px&quot;,&quot;size&quot;:0,&quot;sizes&quot;:[]},&quot;rael_marker_view&quot;:&quot;numbers&quot;,&quot;rael_hierarchical_view&quot;:&quot;yes&quot;,&quot;rael_min_height_tablet&quot;:{&quot;unit&quot;:&quot;px&quot;,&quot;size&quot;:&quot;&quot;,&quot;sizes&quot;:[]},&quot;rael_min_height_mobile&quot;:{&quot;unit&quot;:&quot;px&quot;,&quot;size&quot;:&quot;&quot;,&quot;sizes&quot;:[]}}\" data-widget_type=\"rael-table-of-contents.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t<div class=\"rael-toc__header\">\n\t\t\t\t<h5 class=\"rael-toc__header-title\">\ud83d\udd0dContent: <\/h5>\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<div class=\"rael-toc__body\">\n\t\t\t<div class=\"rael-toc__spinner-container\">\n\t\t\t\t<i class=\"rael-toc__spinner eicon-loading eicon-animation-spin\" aria-hidden=\"true\"><\/i>\n\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-3bc5325 elementor-widget elementor-widget-text-editor\" data-id=\"3bc5325\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t\t<h3>PushButton<\/h3><p>The PushButton is simple and widely used. It <strong>executes a specific action when clicked<\/strong>.<\/p>\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-c20d43c elementor-widget elementor-widget-image\" data-id=\"c20d43c\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"image.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<img decoding=\"async\" width=\"2227\" height=\"302\" src=\"https:\/\/infralligence.com\/wp-content\/uploads\/2024\/12\/c1033987-201e-4d07-bb17-4e16a2eea21d-4.png\" class=\"attachment-full size-full wp-image-2730\" alt=\"\" srcset=\"https:\/\/infralligence.com\/wp-content\/uploads\/2024\/12\/c1033987-201e-4d07-bb17-4e16a2eea21d-4.png 2227w, https:\/\/infralligence.com\/wp-content\/uploads\/2024\/12\/c1033987-201e-4d07-bb17-4e16a2eea21d-4-300x41.png 300w, https:\/\/infralligence.com\/wp-content\/uploads\/2024\/12\/c1033987-201e-4d07-bb17-4e16a2eea21d-4-1024x139.png 1024w, https:\/\/infralligence.com\/wp-content\/uploads\/2024\/12\/c1033987-201e-4d07-bb17-4e16a2eea21d-4-768x104.png 768w, https:\/\/infralligence.com\/wp-content\/uploads\/2024\/12\/c1033987-201e-4d07-bb17-4e16a2eea21d-4-1536x208.png 1536w, https:\/\/infralligence.com\/wp-content\/uploads\/2024\/12\/c1033987-201e-4d07-bb17-4e16a2eea21d-4-2048x278.png 2048w\" sizes=\"(max-width: 2227px) 100vw, 2227px\" \/>\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-9b8a5c6 elementor-widget elementor-widget-text-editor\" data-id=\"9b8a5c6\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t\t<p>We\u2019ve covered PushButtons in detail in a <a href=\"https:\/\/infralligence.com\/pl\/resources\/revit-menu-customization-ribbon-tabs-panels-buttons-textboxes-comboboxes\/\">previous post<\/a>, including how to configure projects to attach images to buttons.<\/p><p>To recap:<\/p><ul class=\"kk-unordered-list-with-arrow\"><li>Create a <strong>PushButtonData<\/strong> to define the button\u2019s name (ID, not visible in Revit), text, and the command to execute when the button is clicked.<\/li><li>Add the PushButtonData to a panel to create a <strong>PushButton<\/strong>.<\/li><li>Customize with tooltips, contextual help, or images.<\/li><\/ul>\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-c6c44e1 elementor-widget elementor-widget-code-block-for-elementor\" data-id=\"c6c44e1\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"code-block-for-elementor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t<pre class='line-numbers theme-default' data-show-toolbar='no'><code class='language-csharp'>var ribbonTabName = &quot;Revit Mastery&quot;;\napplication.CreateRibbonTab(ribbonTabName);\nvar panel = application.CreateRibbonPanel(ribbonTabName, &quot;Revit Mastery Panel&quot;);\n\nvar assemblyPath = Assembly.GetExecutingAssembly().Location; \/\/localization of the currently executing assembly. Don&#039;t worry, copy ;)\nvar assemblyDirectory = Path.GetDirectoryName(assemblyPath);\n\n\n\/\/ PushButton\nvar pushButtonData = new PushButtonData(\n\t&quot;pushButton&quot;,\n\t&quot;Click me&quot;,\n\tassemblyPath,\n\ttypeof(SimpleCommand).FullName);\t\t\n\nvar pushButton = panel.AddItem(pushButtonData) as PushButton;\npushButton.ToolTip = &quot;A simple test button.&quot;;\n\nvar pushButtonContextualHelp = new ContextualHelp(ContextualHelpType.Url, &quot;https:\/\/revitmastery.com\/revit-plugin-types\/&quot;);\npushButton.SetContextualHelp(pushButtonContextualHelp);\n\t\npushButton.LargeImage = new BitmapImage(new Uri(Path.Combine(assemblyDirectory, &quot;Resources&quot;, &quot;Images&quot;, &quot;ads_click_32.png&quot;)));<\/code><\/pre>\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-cc0d22f elementor-widget elementor-widget-text-editor\" data-id=\"cc0d22f\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t\t<p>The\u00a0<strong>command class<\/strong>\u00a0associated with the button must implement the\u00a0<strong>IExternalCommand\u00a0<\/strong>interface.<\/p>\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-00d6e1e elementor-widget elementor-widget-code-block-for-elementor\" data-id=\"00d6e1e\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"code-block-for-elementor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t<pre class='line-numbers theme-default' data-show-toolbar='no'><code class='language-csharp'>[Transaction(TransactionMode.Manual)]\n[Regeneration(RegenerationOption.Manual)]\npublic class SimpleCommand : IExternalCommand\n{\n\tpublic Result Execute(ExternalCommandData commandData, ref string message, ElementSet elements)\n\t{\n\t\tTaskDialog.Show(&quot;Simple command&quot;, &quot;The button has been clicked.&quot;);\n\t\treturn Result.Succeeded;\n\t}\n}<\/code><\/pre>\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-3537586 elementor-widget elementor-widget-text-editor\" data-id=\"3537586\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t\t<h3>PulldownButton<\/h3><p>The PulldownButton provides a <strong>dropdown<\/strong> list of multiple commands.<\/p>\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-28b2da9 elementor-widget elementor-widget-image\" data-id=\"28b2da9\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"image.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<img decoding=\"async\" width=\"2227\" height=\"427\" src=\"https:\/\/infralligence.com\/wp-content\/uploads\/2024\/12\/c1033987-201e-4d07-bb17-4e16a2eea21d-2.png\" class=\"attachment-full size-full wp-image-2732\" alt=\"\" srcset=\"https:\/\/infralligence.com\/wp-content\/uploads\/2024\/12\/c1033987-201e-4d07-bb17-4e16a2eea21d-2.png 2227w, https:\/\/infralligence.com\/wp-content\/uploads\/2024\/12\/c1033987-201e-4d07-bb17-4e16a2eea21d-2-300x58.png 300w, https:\/\/infralligence.com\/wp-content\/uploads\/2024\/12\/c1033987-201e-4d07-bb17-4e16a2eea21d-2-1024x196.png 1024w, https:\/\/infralligence.com\/wp-content\/uploads\/2024\/12\/c1033987-201e-4d07-bb17-4e16a2eea21d-2-768x147.png 768w, https:\/\/infralligence.com\/wp-content\/uploads\/2024\/12\/c1033987-201e-4d07-bb17-4e16a2eea21d-2-1536x295.png 1536w, https:\/\/infralligence.com\/wp-content\/uploads\/2024\/12\/c1033987-201e-4d07-bb17-4e16a2eea21d-2-2048x393.png 2048w\" sizes=\"(max-width: 2227px) 100vw, 2227px\" \/>\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-41d8641 elementor-widget elementor-widget-text-editor\" data-id=\"41d8641\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t\t<p><strong>\u2192 Define options in the drop-down list:<br \/><\/strong>For each option, create a PushButtonData specifying the button\u2019s name (ID, not visible in Revit), text, and the command to execute when clicked. Each option can be customized with a tooltip, contextual help, or an image.<\/p><p><strong>\u2192 Create the PulldownButton:<br \/><\/strong>Create PulldownButtonData to define the button\u2019s name (ID, not visible in Revit) and text. Add the PulldownButtonData to a panel to create the PulldownButton, which can be customized with a tooltip, contextual help, or image.<\/p><p><strong>\u2192 Add options to the PulldownButton.<\/strong><br \/>You can also add separators to divide options in the drop-down list.<\/p>\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-c734cff elementor-widget elementor-widget-code-block-for-elementor\" data-id=\"c734cff\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"code-block-for-elementor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t<pre class='line-numbers theme-default' data-show-toolbar='no'><code class='language-csharp'>\/\/ [...] code before\n\n\/\/ PulldownButton\n\n\/\/1. Defining options\nvar option1Data = new PushButtonData(&quot;option1&quot;, &quot;Walls&quot;, assemblyPath, typeof(SelectWallsCommand).FullName);\noption1Data.ToolTip = &quot;Select walls.&quot;;\noption1Data.LargeImage = new BitmapImage(new Uri(Path.Combine(assemblyDirectory, &quot;Resources&quot;, &quot;Images&quot;, &quot;counter_1_16.png&quot;)));\n\nvar option2Data = new PushButtonData(&quot;option2&quot;, &quot;Floors&quot;, assemblyPath, typeof(SelectFloorsCommand).FullName)\n{\n\t\/\/a different code approach to customize the button\n\tToolTip = &quot;Select floors.&quot;,\n\tLargeImage = new BitmapImage(new Uri(Path.Combine(assemblyDirectory, &quot;Resources&quot;, &quot;Images&quot;, &quot;counter_2_16.png&quot;))),\n};\n\nvar option3Data = new PushButtonData(&quot;option3&quot;, &quot;Stairs&quot;, assemblyPath, typeof(SelectStairsCommand).FullName)\n{\n\tToolTip = &quot;Select stairs.&quot;,\n\tLargeImage = new BitmapImage(new Uri(Path.Combine(assemblyDirectory, &quot;Resources&quot;, &quot;Images&quot;, &quot;counter_3_16.png&quot;)))\n};\n\n\n\/\/ 2. Defining the PulldownButton\nvar pulldownButtonData = new PulldownButtonData(&quot;pulldownButton&quot;, &quot;Select elements&quot;);\nvar pulldownButton = panel.AddItem(pulldownButtonData) as PulldownButton;\npulldownButton.LargeImage = new BitmapImage(new Uri(Path.Combine(assemblyDirectory, &quot;Resources&quot;, &quot;Images&quot;, &quot;widgets_32.png&quot;)));\n\n\n\/\/ 3. Adding options to the PulldownButton (with optional separator)\npulldownButton.AddPushButton(option1Data);\npulldownButton.AddPushButton(option2Data);\npulldownButton.AddSeparator();\npulldownButton.AddPushButton(option3Data);<\/code><\/pre>\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-3e57424 elementor-widget elementor-widget-code-block-for-elementor\" data-id=\"3e57424\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"code-block-for-elementor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t<pre class='line-numbers theme-default' data-show-toolbar='no'><code class='language-csharp'>[Transaction(TransactionMode.Manual)]\n[Regeneration(RegenerationOption.Manual)]\npublic class SelectWallsCommand : IExternalCommand\n{\n\tpublic Result Execute(ExternalCommandData commandData, ref string message, ElementSet elements)\n\t{\n\t\tvar uiApp = commandData.Application;\n\t\tvar doc = uiApp.ActiveUIDocument.Document;\n\t\tvar selectionManager = uiApp.ActiveUIDocument.Selection;\n\n\t\tvar elementsType = typeof(Wall);\n\t\tvar collector = new FilteredElementCollector(doc).WhereElementIsNotElementType().OfClass(elementsType);\n\t\tvar collectedElementsIds = collector.ToElementIds();\n\t\t\n\t\tselectionManager.SetElementIds(collectedElementsIds);\n            \n\t\treturn Result.Succeeded;\n\t}\n}\n\n[Transaction(TransactionMode.Manual)]\n[Regeneration(RegenerationOption.Manual)]\npublic class SelectFloorsCommand : IExternalCommand\n{\n\tpublic Result Execute(ExternalCommandData commandData, ref string message, ElementSet elements)\n\t{\n\t\tvar uiApp = commandData.Application;\n\t\tvar doc = uiApp.ActiveUIDocument.Document;\n\t\tvar selectionManager = uiApp.ActiveUIDocument.Selection;\n\n\t\tvar elementsType = typeof(Floor);\n\t\tvar collector = new FilteredElementCollector(doc).WhereElementIsNotElementType().OfClass(elementsType);\n\t\tvar collectedElementsIds = collector.ToElementIds();\n\n\t\tselectionManager.SetElementIds(collectedElementsIds);\n\n\t\treturn Result.Succeeded;\n\t}\n}\n\n[Transaction(TransactionMode.Manual)]\n[Regeneration(RegenerationOption.Manual)]\npublic class SelectStairsCommand : IExternalCommand\n{\n\tpublic Result Execute(ExternalCommandData commandData, ref string message, ElementSet elements)\n\t{\n\t\tvar uiApp = commandData.Application;\n\t\tvar doc = uiApp.ActiveUIDocument.Document;\n\t\tvar selectionManager = uiApp.ActiveUIDocument.Selection;\n\n\t\tvar elementsType = typeof(Stairs);\n\t\tvar collector = new FilteredElementCollector(doc).WhereElementIsNotElementType().OfClass(elementsType);\n\t\tvar collectedElementsIds = collector.ToElementIds();\n\n\t\tselectionManager.SetElementIds(collectedElementsIds);\n\n\t\treturn Result.Succeeded;\n\t}\n}<\/code><\/pre>\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-3d0f77b elementor-widget elementor-widget-text-editor\" data-id=\"3d0f77b\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t\t<div class=\"kk-infobox-info\"><strong>\u2139\ufe0f <\/strong><strong>Avoiding Repetitions in Command Classes<\/strong><\/div><div class=\"kk-infobox-info\">Each option requires a separate command class. But the classes are almost identical; each performs the same action and differs only in the element type (Walls\/Floors\/Stairs). It leads to repeating code, which is a bad practice.<\/div><div class=\"kk-infobox-info\">To overcome repetitions, use C# inheritance and generics to create a parent abstract class and subclasses for specific Revit element types.<\/div>\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-f70776f kk-infobox-info elementor-widget elementor-widget-code-block-for-elementor\" data-id=\"f70776f\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"code-block-for-elementor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t<pre class='line-numbers theme-default' data-show-toolbar='no'><code class='language-csharp'>[Transaction(TransactionMode.Manual)]\n[Regeneration(RegenerationOption.Manual)]\npublic class SelectWallsCommand : SelectElementsOfTypeCommand&lt;Wall&gt;;\n\n[Transaction(TransactionMode.Manual)]\n[Regeneration(RegenerationOption.Manual)]\npublic class SelectFloorsCommand : SelectElementsOfTypeCommand&lt;Floor&gt;;\n\n[Transaction(TransactionMode.Manual)]\n[Regeneration(RegenerationOption.Manual)]\npublic class SelectStairsCommand : SelectElementsOfTypeCommand&lt;Stairs&gt;;\n\npublic abstract class SelectElementsOfTypeCommand&lt;TRevitElementType&gt; : IExternalCommand where TRevitElementType : Element\n{\n\tpublic Result Execute(ExternalCommandData commandData, ref string message, ElementSet elements)\n\t{\n\t\tvar uiApp = commandData.Application;\n\t\tvar doc = uiApp.ActiveUIDocument.Document;\n\t\tvar selectionManager = uiApp.ActiveUIDocument.Selection;\n\n\t\tvar elementsType = typeof(TRevitElementType);\n\t\tvar collector = new FilteredElementCollector(doc).WhereElementIsNotElementType().OfClass(elementsType);\n\t\tvar collectedElementsIds = collector.ToElementIds();\n\n\t\tselectionManager.SetElementIds(collectedElementsIds);\n\n\t\treturn Result.Succeeded;\n\t}\n}<\/code><\/pre>\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-5c05c39 elementor-widget elementor-widget-text-editor\" data-id=\"5c05c39\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t\t<div class=\"kk-infobox-info\">It simplifies code maintenance. Now, to modify logic, you change the code in a single place, not in each class. Effective and error-prone.<\/div>\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-f5143c5 elementor-widget elementor-widget-text-editor\" data-id=\"f5143c5\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t\t<h3>SplitButton<\/h3><p>The SplitButton is an enhanced version of the PulldownButton. <strong>In addition to the drop-down list, it displays the last clicked (or default) option as a separate button<\/strong> allowing quicker access.<\/p>\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-9cb01f0 elementor-widget elementor-widget-image\" data-id=\"9cb01f0\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"image.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<img loading=\"lazy\" decoding=\"async\" width=\"2229\" height=\"400\" src=\"https:\/\/infralligence.com\/wp-content\/uploads\/2024\/12\/c1033987-201e-4d07-bb17-4e16a2eea21d-1.png\" class=\"attachment-full size-full wp-image-2733\" alt=\"\" srcset=\"https:\/\/infralligence.com\/wp-content\/uploads\/2024\/12\/c1033987-201e-4d07-bb17-4e16a2eea21d-1.png 2229w, https:\/\/infralligence.com\/wp-content\/uploads\/2024\/12\/c1033987-201e-4d07-bb17-4e16a2eea21d-1-300x54.png 300w, https:\/\/infralligence.com\/wp-content\/uploads\/2024\/12\/c1033987-201e-4d07-bb17-4e16a2eea21d-1-1024x184.png 1024w, https:\/\/infralligence.com\/wp-content\/uploads\/2024\/12\/c1033987-201e-4d07-bb17-4e16a2eea21d-1-768x138.png 768w, https:\/\/infralligence.com\/wp-content\/uploads\/2024\/12\/c1033987-201e-4d07-bb17-4e16a2eea21d-1-1536x276.png 1536w, https:\/\/infralligence.com\/wp-content\/uploads\/2024\/12\/c1033987-201e-4d07-bb17-4e16a2eea21d-1-2048x368.png 2048w\" sizes=\"(max-width: 2229px) 100vw, 2229px\" \/>\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-3f6d61e elementor-widget elementor-widget-text-editor\" data-id=\"3f6d61e\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t\t<p>\u2192 <strong>Define options in the drop-down list:<\/strong><br \/>For each option, create a PushButtonData specifying the button\u2019s name (ID, not visible in Revit), text, and the command to execute when clicked. Each option can be customized with a tooltip, contextual help, or an image.<\/p><p>\u2192 <strong>Create the SplitButton:<\/strong><br \/>Create SplitButtonData to define the button\u2019s name (ID, not visible in Revit) and text. Add the SplitButtonData to a panel to create the SplitButton, which can be customized with a tooltip, contextual help, or image.<\/p><p>\u2192 <strong>Add options to the SplitButton.<\/strong><br \/>You can also add separators to divide options in the drop-down list.<\/p>\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-0e29233 kk-infobox-info elementor-widget elementor-widget-code-block-for-elementor\" data-id=\"0e29233\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"code-block-for-elementor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t<pre class='line-numbers theme-default' data-show-toolbar='no'><code class='language-csharp'>\/\/ SplitButton\n\n\/\/ 1. Defining options (in our case, the same for PulldownButton and SplitButton)\n\/\/ [... preevious code]\n\n\/\/ 2. Defining the SplitButton\nvar splitButtonData = new SplitButtonData(&quot;splitButton&quot;, &quot;Split button&quot;);\nvar splitButton = panel.AddItem(splitButtonData) as SplitButton;\n\n\/\/ 3. Adding options to the SplitButton (with optional separator)\nsplitButton.AddPushButton(option1Data);\nsplitButton.AddPushButton(option2Data);\nsplitButton.AddSeparator();\nsplitButton.AddPushButton(option3Data);<\/code><\/pre>\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-6e29770 elementor-widget elementor-widget-text-editor\" data-id=\"6e29770\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t\t<h3>RadioButtonGroup<\/h3><p>The RadioButtonGroup is a <strong>group of toggle buttons of which only one can be selected<\/strong>. The RadioButtonGroup <strong>sets user preferences<\/strong>.<\/p><p>In our example, the user will select whether a single or all Revit elements (Walls\/Floors\/Stairs) should be selected when the user clicks the previous buttons.<\/p>\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-450c8e4 elementor-widget elementor-widget-image\" data-id=\"450c8e4\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"image.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<img loading=\"lazy\" decoding=\"async\" width=\"2227\" height=\"392\" src=\"https:\/\/infralligence.com\/wp-content\/uploads\/2024\/12\/c1033987-201e-4d07-bb17-4e16a2eea21d-3.png\" class=\"attachment-full size-full wp-image-2731\" alt=\"\" srcset=\"https:\/\/infralligence.com\/wp-content\/uploads\/2024\/12\/c1033987-201e-4d07-bb17-4e16a2eea21d-3.png 2227w, https:\/\/infralligence.com\/wp-content\/uploads\/2024\/12\/c1033987-201e-4d07-bb17-4e16a2eea21d-3-300x53.png 300w, https:\/\/infralligence.com\/wp-content\/uploads\/2024\/12\/c1033987-201e-4d07-bb17-4e16a2eea21d-3-1024x180.png 1024w, https:\/\/infralligence.com\/wp-content\/uploads\/2024\/12\/c1033987-201e-4d07-bb17-4e16a2eea21d-3-768x135.png 768w, https:\/\/infralligence.com\/wp-content\/uploads\/2024\/12\/c1033987-201e-4d07-bb17-4e16a2eea21d-3-1536x270.png 1536w, https:\/\/infralligence.com\/wp-content\/uploads\/2024\/12\/c1033987-201e-4d07-bb17-4e16a2eea21d-3-2048x360.png 2048w\" sizes=\"(max-width: 2227px) 100vw, 2227px\" \/>\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-b6782e4 elementor-widget elementor-widget-text-editor\" data-id=\"b6782e4\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t\t<p>\u2192 <strong>Define ToggleButtons as options in the group:<\/strong><br \/>For each option, create a ToggleButtonData specifying the toggle button\u2019s name (ID, not visible in Revit), and text. Each option can be customized with a tooltip, contextual help, or an image.<\/p><p>\u2192 <strong>Create the RadioButtonGroup:<\/strong><br \/>Create RadioButtonGroupData to define the radio button\u2019s name (ID, not visible in Revit). Add the RadioButtonGroupData to a panel to create the RadioButtonGroup.<\/p><p>\u2192 <strong>Add options to the RadioButtonGroup.<\/strong><\/p><p>\u2192 <strong>Assign the RadioButtonGroup to a global variable:<\/strong><br \/>Store the RadioButtonGroup in a private static variable, and create a public static property to retrieve the selected option.<\/p>\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-413d18d kk-infobox-info elementor-widget elementor-widget-code-block-for-elementor\" data-id=\"413d18d\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"code-block-for-elementor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t<pre class='line-numbers theme-default' data-show-toolbar='no'><code class='language-csharp'>[Transaction(TransactionMode.Manual)]\n[Regeneration(RegenerationOption.Manual)]\npublic class RevitMasteryApplication : IExternalApplication\n{\n\t\/\/ 4.1 Needed to access the RadioButton value elsewhere\n\tprivate static RadioButtonGroup radioButton;\n\tpublic static bool ShouldSingleElementBeSelected =&gt; radioButton.Current.ItemText == &quot;Single&quot;;\t\t\t\n\n\tpublic Result OnStartup(UIControlledApplication application)\n\t{\n\t\t\/\/ [... previous code]\n\n\t\t\/\/ RadioButton\n\n\t\t\/\/1. Defining options\n\t\tvar toggleButtonData1 = new ToggleButtonData(&quot;toggleButton1&quot;, &quot;Single&quot;)\n\t\t{\n\t\t\tToolTip = &quot;Set to select a single element of type.&quot;,\n\t\t\tLargeImage = new BitmapImage(new Uri(Path.Combine(assemblyDirectory, &quot;Resources&quot;, &quot;Images&quot;, &quot;single_16.png&quot;))),\n\t\t};\n\t\tvar toggleButtonData2 = new ToggleButtonData(&quot;toggleButton2&quot;, &quot;All&quot;)\n\t\t{\n\t\t\tToolTip = &quot;Set to select all elements of type.&quot;,\n\t\t\tLargeImage = new BitmapImage(new Uri(Path.Combine(assemblyDirectory, &quot;Resources&quot;, &quot;Images&quot;, &quot;multiple_16.png&quot;))),\n\t\t};\n\n\t\t\/\/2. Defining the RadioButton\n\t\tvar radioButtonData = new RadioButtonGroupData(&quot;radioButtonGroup&quot;);\n\t\tvar radioButton = panel.AddItem(radioButtonData) as RadioButtonGroup;\n\n\t\t\/\/3. Adding options to the RadioButton\n\t\tradioButton.AddItem(toggleButtonData1);\n\t\tradioButton.AddItem(toggleButtonData2);\n\n\t\t\/\/4. Assigning the RadioButton to a global variable (to use its value elsewhere)\n\t\tRevitMasteryApplication.radioButton = radioButton;\n\n\t\treturn Result.Succeeded;\n\t}\n}<\/code><\/pre>\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-e757316 elementor-widget elementor-widget-text-editor\" data-id=\"e757316\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t\t<h3>The Final Code<\/h3><p>To select single\/all elements, depending on the option from the RadioButtonGroup, we have to modify SelectWallsCommand, SelectFloorsCommand, and SelectStairCommand (or just SelectElementsOfTypeCommand in the \u201cnon-repetitions\u201d approach).<\/p>\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-a1a1e21 kk-infobox-info elementor-widget elementor-widget-code-block-for-elementor\" data-id=\"a1a1e21\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"code-block-for-elementor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t<pre class='line-numbers theme-default' data-show-toolbar='no'><code class='language-csharp'>using System.IO;\nusing System.Reflection;\nusing System.Windows.Media.Imaging;\nusing Autodesk.Revit.Attributes;\nusing Autodesk.Revit.DB;\nusing Autodesk.Revit.UI;\nusing RevitMastery.Revit.Commands;\n\nnamespace RevitMastery.Revit;\n\n[Transaction(TransactionMode.Manual)]\n[Regeneration(RegenerationOption.Manual)]\npublic class RevitMasteryApplication : IExternalApplication\n{\n\t\/\/ 4.1 Needed to access the RadioButton value elsewhere\n\tprivate static RadioButtonGroup radioButton;\n\tpublic static bool ShouldSingleElementBeSelected =&gt; radioButton.Current.ItemText == &quot;Single&quot;;\n\n\tpublic Result OnStartup(UIControlledApplication application)\n\t{\n\t\tvar ribbonTabName = &quot;Revit Mastery&quot;;\n\t\tapplication.CreateRibbonTab(ribbonTabName);\n\t\tvar panel = application.CreateRibbonPanel(ribbonTabName, &quot;Revit Mastery Panel&quot;);\n\n\t\tvar assemblyPath = Assembly.GetExecutingAssembly().Location; \/\/localization of the currently executing assembly. Don&#039;t worry, copy ;)\n\t\tvar assemblyDirectory = Path.GetDirectoryName(assemblyPath);\n\n\n\t\t\/\/ PushButton\n\t\tvar pushButtonData = new PushButtonData(\n\t\t\t&quot;pushButton&quot;,\n\t\t\t&quot;Click me&quot;,\n\t\t\tassemblyPath,\n\t\t\ttypeof(SimpleCommand).FullName);\n\n\t\tvar pushButton = panel.AddItem(pushButtonData) as PushButton;\n\t\tpushButton.ToolTip = &quot;A simple test button.&quot;;\n\n\t\tvar pushButtonContextualHelp = new ContextualHelp(ContextualHelpType.Url, &quot;https:\/\/revitmastery.com\/revit-plugin-types\/&quot;);\n\t\tpushButton.SetContextualHelp(pushButtonContextualHelp);\n\t\t\t\n\t\tpushButton.LargeImage = new BitmapImage(new Uri(Path.Combine(assemblyDirectory, &quot;Resources&quot;, &quot;Images&quot;, &quot;ads_click_32.png&quot;)));\n\n\n\t\t\/\/ PulldownButton\n\n\t\t\/\/ 1. Defining options (in our case, the same for PulldownButton and SplitButton)\n\t\tvar option1Data = new PushButtonData(&quot;option1&quot;, &quot;Walls&quot;, assemblyPath, typeof(SelectWallsCommand).FullName);\n\t\toption1Data.ToolTip = &quot;Select walls.&quot;;\n\t\toption1Data.LargeImage = new BitmapImage(new Uri(Path.Combine(assemblyDirectory, &quot;Resources&quot;, &quot;Images&quot;, &quot;counter_1_16.png&quot;)));\n\n\t\tvar option2Data = new PushButtonData(&quot;option2&quot;, &quot;Floors&quot;, assemblyPath, typeof(SelectFloorsCommand).FullName)\n\t\t{\n\t\t\t\/\/ a different code approach to customize the button\n\t\t\tToolTip = &quot;Select floors.&quot;,\n\t\t\tLargeImage = new BitmapImage(new Uri(Path.Combine(assemblyDirectory, &quot;Resources&quot;, &quot;Images&quot;, &quot;counter_2_16.png&quot;))),\n\t\t};\n\n\t\tvar option3Data = new PushButtonData(&quot;option3&quot;, &quot;Stairs&quot;, assemblyPath, typeof(SelectStairsCommand).FullName)\n\t\t{\n\t\t\tToolTip = &quot;Select stairs.&quot;,\n\t\t\tLargeImage = new BitmapImage(new Uri(Path.Combine(assemblyDirectory, &quot;Resources&quot;, &quot;Images&quot;, &quot;counter_3_16.png&quot;)))\n\t\t};\n\n\t\t\/\/ 2. Defining the PulldownButton\n\t\tvar pulldownButtonData = new PulldownButtonData(&quot;pulldownButton&quot;, &quot;Select elements&quot;);\n\t\tvar pulldownButton = panel.AddItem(pulldownButtonData) as PulldownButton;\n\t\tpulldownButton.LargeImage = new BitmapImage(new Uri(Path.Combine(assemblyDirectory, &quot;Resources&quot;, &quot;Images&quot;, &quot;widgets_32.png&quot;)));\n\n\t\t\/\/ 3. Adding options to the PulldownButton (with optional separator)\n\t\tpulldownButton.AddPushButton(option1Data);\n\t\tpulldownButton.AddPushButton(option2Data);\n\t\tpulldownButton.AddSeparator();\n\t\tpulldownButton.AddPushButton(option3Data);\n\n\n\t\t\/\/ SplitButton\n\n\t\t\/\/2. Defining the SplitButton\n\t\tvar splitButtonData = new SplitButtonData(&quot;splitButton&quot;, &quot;Split button&quot;);\n\t\tvar splitButton = panel.AddItem(splitButtonData) as SplitButton;\n\n\t\t\/\/ 3. Adding options to the SplitButton (with optional separator)\n\t\tsplitButton.AddPushButton(option1Data);\n\t\tsplitButton.AddPushButton(option2Data);\n\t\tsplitButton.AddSeparator();\n\t\tsplitButton.AddPushButton(option3Data);\n\n\n\t\t\/\/ RadioButton\n\n\t\t\/\/1. Defining options\n\t\tvar toggleButtonData1 = new ToggleButtonData(&quot;toggleButton1&quot;, &quot;Single&quot;)\n\t\t{\n\t\t\tToolTip = &quot;Set to select a single element of type.&quot;,\n\t\t\tLargeImage = new BitmapImage(new Uri(Path.Combine(assemblyDirectory, &quot;Resources&quot;, &quot;Images&quot;, &quot;single_16.png&quot;))),\n\t\t};\n\t\tvar toggleButtonData2 = new ToggleButtonData(&quot;toggleButton2&quot;, &quot;All&quot;)\n\t\t{\n\t\t\tToolTip = &quot;Set to select all elements of type.&quot;,\n\t\t\tLargeImage = new BitmapImage(new Uri(Path.Combine(assemblyDirectory, &quot;Resources&quot;, &quot;Images&quot;, &quot;multiple_16.png&quot;))),\n\t\t};\n\n\t\t\/\/2. Defining the RadioButton\n\t\tvar radioButtonData = new RadioButtonGroupData(&quot;radioButtonGroup&quot;);\n\t\tvar radioButton = panel.AddItem(radioButtonData) as RadioButtonGroup;\n\n\n\t\t\/\/3. Adding options to the RadioButton\n\t\tradioButton.AddItem(toggleButtonData1);\n\t\tradioButton.AddItem(toggleButtonData2);\n\n\t\t\/\/4. Assigning the RadioButton to a global variable (to use its value elsewhere)\n\t\tRevitMasteryApplication.radioButton = radioButton;\n\n\t\treturn Result.Succeeded;\n\t}\n\n\tpublic Result OnShutdown(UIControlledApplication application)\n\t{\n\t\treturn Result.Succeeded;\n\t}\n}<\/code><\/pre>\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-4677c13 kk-infobox-info elementor-widget elementor-widget-code-block-for-elementor\" data-id=\"4677c13\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"code-block-for-elementor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t<pre class='line-numbers theme-default' data-show-toolbar='no'><code class='language-csharp'>using Autodesk.Revit.Attributes;\nusing Autodesk.Revit.UI;\nusing Autodesk.Revit.DB;\nusing Autodesk.Revit.DB.Architecture;\n\nnamespace RevitMastery.Revit.Commands;\n\n[Transaction(TransactionMode.Manual)]\n[Regeneration(RegenerationOption.Manual)]\npublic class SelectWallsCommand : SelectElementsOfTypeCommand&lt;Wall&gt;;\n\n[Transaction(TransactionMode.Manual)]\n[Regeneration(RegenerationOption.Manual)]\npublic class SelectFloorsCommand : SelectElementsOfTypeCommand&lt;Floor&gt;;\n\n[Transaction(TransactionMode.Manual)]\n[Regeneration(RegenerationOption.Manual)]\npublic class SelectStairsCommand : SelectElementsOfTypeCommand&lt;Stairs&gt;;\n\npublic abstract class SelectElementsOfTypeCommand&lt;TRevitElementType&gt; : IExternalCommand where TRevitElementType : Element\n{\n\tpublic Result Execute(ExternalCommandData commandData, ref string message, ElementSet elements)\n\t{\n\t\tvar uiApp = commandData.Application;\n\t\tvar doc = uiApp.ActiveUIDocument.Document;\n\t\tvar selectionManager = uiApp.ActiveUIDocument.Selection;\n\n\t\tvar elementsType = typeof(TRevitElementType);\n\t\tvar collector = new FilteredElementCollector(doc).WhereElementIsNotElementType().OfClass(elementsType);\n\t\tvar collectedElementsIds = collector.ToElementIds();\n\n\t\tif (RevitMasteryApplication.ShouldSingleElementBeSelected)\n\t\t{\n\t\t\tvar firstElementId = collectedElementsIds.First();\n\t\t\tselectionManager.SetElementIds(new List&lt;ElementId&gt; { firstElementId });\n\t\t}\n\t\telse\n\t\t{\n\t\t\tselectionManager.SetElementIds(collectedElementsIds);\n\t\t}\n\n\t\treturn Result.Succeeded;\n\t}\n}<\/code><\/pre>\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<\/div>","protected":false},"excerpt":{"rendered":"<p>Revit API offers several types of buttons to enhance your plugin\u2019s UI: PushButton (most common), PulldownButton, SplitButton, and RadioButtonGroup. \ud83d\udccc TLDR \u2013 Summary Upfront: \u27a1\ufe0f Use PushButtons for single commands. \u27a1\ufe0f Use PulldownButtons and SplitButtons to group similar commands. \u27a1\ufe0f Use RadioButtonGroups to let users set preferences. Avoid repetitions in command classes: use C# inheritance [&hellip;]<\/p>","protected":false},"author":2,"featured_media":0,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"site-sidebar-layout":"default","site-content-layout":"","ast-site-content-layout":"default","site-content-style":"default","site-sidebar-style":"default","ast-global-header-display":"","ast-banner-title-visibility":"","ast-main-header-display":"","ast-hfb-above-header-display":"","ast-hfb-below-header-display":"","ast-hfb-mobile-header-display":"","site-post-title":"","ast-breadcrumbs-content":"","ast-featured-img":"","footer-sml-layout":"","ast-disable-related-posts":"","theme-transparent-header-meta":"","adv-header-id-meta":"","stick-header-meta":"","header-above-stick-meta":"","header-main-stick-meta":"","header-below-stick-meta":"","astra-migrate-meta-layouts":"set","ast-page-background-enabled":"default","ast-page-background-meta":{"desktop":{"background-color":"var(--ast-global-color-4)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"tablet":{"background-color":"","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"mobile":{"background-color":"","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""}},"ast-content-background-meta":{"desktop":{"background-color":"var(--ast-global-color-5)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"tablet":{"background-color":"var(--ast-global-color-5)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"mobile":{"background-color":"var(--ast-global-color-5)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""}},"footnotes":""},"categories":[6],"tags":[],"post_folder":[],"class_list":["post-2727","post","type-post","status-publish","format-standard","hentry","category-revit-api-basics"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v23.9 - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>Buttons in Revit API: PushButton, PulldownButton, SplitButton, RadioButtonGroup - Infralligence<\/title>\n<meta name=\"description\" content=\"Revit API offers several types of buttons: PushButton, PulldownButtons, SplitButtons, and RadioButtonGroups...\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/infralligence.com\/pl\/resources\/buttons-in-revit-api-pushbutton-pulldownbutton-splitbutton-radiobuttongroup\/\" \/>\n<meta property=\"og:locale\" content=\"pl_PL\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Buttons in Revit API: PushButton, PulldownButton, SplitButton, RadioButtonGroup - Infralligence\" \/>\n<meta property=\"og:description\" content=\"Revit API offers several types of buttons: PushButton, PulldownButtons, SplitButtons, and RadioButtonGroups...\" \/>\n<meta property=\"og:url\" content=\"https:\/\/infralligence.com\/pl\/resources\/buttons-in-revit-api-pushbutton-pulldownbutton-splitbutton-radiobuttongroup\/\" \/>\n<meta property=\"og:site_name\" content=\"Infralligence\" \/>\n<meta property=\"article:published_time\" content=\"2024-09-04T08:43:44+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2024-12-31T09:30:01+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/infralligence.com\/wp-content\/uploads\/2024\/12\/c1033987-201e-4d07-bb17-4e16a2eea21d.png\" \/>\n\t<meta property=\"og:image:width\" content=\"2560\" \/>\n\t<meta property=\"og:image:height\" content=\"1440\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/png\" \/>\n<meta name=\"author\" content=\"Kamil Korus\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Napisane przez\" \/>\n\t<meta name=\"twitter:data1\" content=\"Kamil Korus\" \/>\n\t<meta name=\"twitter:label2\" content=\"Szacowany czas czytania\" \/>\n\t<meta name=\"twitter:data2\" content=\"5 minut\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\/\/infralligence.com\/resources\/buttons-in-revit-api-pushbutton-pulldownbutton-splitbutton-radiobuttongroup\/#article\",\"isPartOf\":{\"@id\":\"https:\/\/infralligence.com\/resources\/buttons-in-revit-api-pushbutton-pulldownbutton-splitbutton-radiobuttongroup\/\"},\"author\":{\"name\":\"Kamil Korus\",\"@id\":\"https:\/\/infralligence.com\/#\/schema\/person\/838177275b7d3b8b217b13180a74aeda\"},\"headline\":\"Buttons in Revit API: PushButton, PulldownButton, SplitButton, RadioButtonGroup\",\"datePublished\":\"2024-09-04T08:43:44+00:00\",\"dateModified\":\"2024-12-31T09:30:01+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/infralligence.com\/resources\/buttons-in-revit-api-pushbutton-pulldownbutton-splitbutton-radiobuttongroup\/\"},\"wordCount\":666,\"publisher\":{\"@id\":\"https:\/\/infralligence.com\/#organization\"},\"image\":{\"@id\":\"https:\/\/infralligence.com\/resources\/buttons-in-revit-api-pushbutton-pulldownbutton-splitbutton-radiobuttongroup\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/infralligence.com\/wp-content\/uploads\/2024\/12\/c1033987-201e-4d07-bb17-4e16a2eea21d.png\",\"articleSection\":[\"Revit API Basics\"],\"inLanguage\":\"pl-PL\"},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/infralligence.com\/resources\/buttons-in-revit-api-pushbutton-pulldownbutton-splitbutton-radiobuttongroup\/\",\"url\":\"https:\/\/infralligence.com\/resources\/buttons-in-revit-api-pushbutton-pulldownbutton-splitbutton-radiobuttongroup\/\",\"name\":\"Buttons in Revit API: PushButton, PulldownButton, SplitButton, RadioButtonGroup - Infralligence\",\"isPartOf\":{\"@id\":\"https:\/\/infralligence.com\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/infralligence.com\/resources\/buttons-in-revit-api-pushbutton-pulldownbutton-splitbutton-radiobuttongroup\/#primaryimage\"},\"image\":{\"@id\":\"https:\/\/infralligence.com\/resources\/buttons-in-revit-api-pushbutton-pulldownbutton-splitbutton-radiobuttongroup\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/infralligence.com\/wp-content\/uploads\/2024\/12\/c1033987-201e-4d07-bb17-4e16a2eea21d.png\",\"datePublished\":\"2024-09-04T08:43:44+00:00\",\"dateModified\":\"2024-12-31T09:30:01+00:00\",\"description\":\"Revit API offers several types of buttons: PushButton, PulldownButtons, SplitButtons, and RadioButtonGroups...\",\"breadcrumb\":{\"@id\":\"https:\/\/infralligence.com\/resources\/buttons-in-revit-api-pushbutton-pulldownbutton-splitbutton-radiobuttongroup\/#breadcrumb\"},\"inLanguage\":\"pl-PL\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/infralligence.com\/resources\/buttons-in-revit-api-pushbutton-pulldownbutton-splitbutton-radiobuttongroup\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"pl-PL\",\"@id\":\"https:\/\/infralligence.com\/resources\/buttons-in-revit-api-pushbutton-pulldownbutton-splitbutton-radiobuttongroup\/#primaryimage\",\"url\":\"https:\/\/infralligence.com\/wp-content\/uploads\/2024\/12\/c1033987-201e-4d07-bb17-4e16a2eea21d.png\",\"contentUrl\":\"https:\/\/infralligence.com\/wp-content\/uploads\/2024\/12\/c1033987-201e-4d07-bb17-4e16a2eea21d.png\"},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/infralligence.com\/resources\/buttons-in-revit-api-pushbutton-pulldownbutton-splitbutton-radiobuttongroup\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/infralligence.com\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Buttons in Revit API: PushButton, PulldownButton, SplitButton, RadioButtonGroup\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/infralligence.com\/#website\",\"url\":\"https:\/\/infralligence.com\/\",\"name\":\"Infralligence\",\"description\":\"Digital Automation and AI for civil engineering\",\"publisher\":{\"@id\":\"https:\/\/infralligence.com\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/infralligence.com\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"pl-PL\"},{\"@type\":\"Organization\",\"@id\":\"https:\/\/infralligence.com\/#organization\",\"name\":\"Infralligence\",\"url\":\"https:\/\/infralligence.com\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"pl-PL\",\"@id\":\"https:\/\/infralligence.com\/#\/schema\/logo\/image\/\",\"url\":\"https:\/\/infralligence.com\/wp-content\/uploads\/2024\/11\/android-chrome-192x192-1.png\",\"contentUrl\":\"https:\/\/infralligence.com\/wp-content\/uploads\/2024\/11\/android-chrome-192x192-1.png\",\"width\":192,\"height\":192,\"caption\":\"Infralligence\"},\"image\":{\"@id\":\"https:\/\/infralligence.com\/#\/schema\/logo\/image\/\"}},{\"@type\":\"Person\",\"@id\":\"https:\/\/infralligence.com\/#\/schema\/person\/838177275b7d3b8b217b13180a74aeda\",\"name\":\"Kamil Korus\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"pl-PL\",\"@id\":\"https:\/\/infralligence.com\/#\/schema\/person\/image\/\",\"url\":\"https:\/\/secure.gravatar.com\/avatar\/95bd7da2ac29ff34a2ab9bf4ea30273b?s=96&d=mm&r=g\",\"contentUrl\":\"https:\/\/secure.gravatar.com\/avatar\/95bd7da2ac29ff34a2ab9bf4ea30273b?s=96&d=mm&r=g\",\"caption\":\"Kamil Korus\"},\"sameAs\":[\"https:\/\/www.linkedin.com\/in\/kamil-korus\/\"],\"url\":\"https:\/\/infralligence.com\/pl\/resources\/author\/kamil-korus\/\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Buttons in Revit API: PushButton, PulldownButton, SplitButton, RadioButtonGroup - Infralligence","description":"Revit API offers several types of buttons: PushButton, PulldownButtons, SplitButtons, and RadioButtonGroups...","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/infralligence.com\/pl\/resources\/buttons-in-revit-api-pushbutton-pulldownbutton-splitbutton-radiobuttongroup\/","og_locale":"pl_PL","og_type":"article","og_title":"Buttons in Revit API: PushButton, PulldownButton, SplitButton, RadioButtonGroup - Infralligence","og_description":"Revit API offers several types of buttons: PushButton, PulldownButtons, SplitButtons, and RadioButtonGroups...","og_url":"https:\/\/infralligence.com\/pl\/resources\/buttons-in-revit-api-pushbutton-pulldownbutton-splitbutton-radiobuttongroup\/","og_site_name":"Infralligence","article_published_time":"2024-09-04T08:43:44+00:00","article_modified_time":"2024-12-31T09:30:01+00:00","og_image":[{"width":2560,"height":1440,"url":"https:\/\/infralligence.com\/wp-content\/uploads\/2024\/12\/c1033987-201e-4d07-bb17-4e16a2eea21d.png","type":"image\/png"}],"author":"Kamil Korus","twitter_card":"summary_large_image","twitter_misc":{"Napisane przez":"Kamil Korus","Szacowany czas czytania":"5 minut"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/infralligence.com\/resources\/buttons-in-revit-api-pushbutton-pulldownbutton-splitbutton-radiobuttongroup\/#article","isPartOf":{"@id":"https:\/\/infralligence.com\/resources\/buttons-in-revit-api-pushbutton-pulldownbutton-splitbutton-radiobuttongroup\/"},"author":{"name":"Kamil Korus","@id":"https:\/\/infralligence.com\/#\/schema\/person\/838177275b7d3b8b217b13180a74aeda"},"headline":"Buttons in Revit API: PushButton, PulldownButton, SplitButton, RadioButtonGroup","datePublished":"2024-09-04T08:43:44+00:00","dateModified":"2024-12-31T09:30:01+00:00","mainEntityOfPage":{"@id":"https:\/\/infralligence.com\/resources\/buttons-in-revit-api-pushbutton-pulldownbutton-splitbutton-radiobuttongroup\/"},"wordCount":666,"publisher":{"@id":"https:\/\/infralligence.com\/#organization"},"image":{"@id":"https:\/\/infralligence.com\/resources\/buttons-in-revit-api-pushbutton-pulldownbutton-splitbutton-radiobuttongroup\/#primaryimage"},"thumbnailUrl":"https:\/\/infralligence.com\/wp-content\/uploads\/2024\/12\/c1033987-201e-4d07-bb17-4e16a2eea21d.png","articleSection":["Revit API Basics"],"inLanguage":"pl-PL"},{"@type":"WebPage","@id":"https:\/\/infralligence.com\/resources\/buttons-in-revit-api-pushbutton-pulldownbutton-splitbutton-radiobuttongroup\/","url":"https:\/\/infralligence.com\/resources\/buttons-in-revit-api-pushbutton-pulldownbutton-splitbutton-radiobuttongroup\/","name":"Buttons in Revit API: PushButton, PulldownButton, SplitButton, RadioButtonGroup - Infralligence","isPartOf":{"@id":"https:\/\/infralligence.com\/#website"},"primaryImageOfPage":{"@id":"https:\/\/infralligence.com\/resources\/buttons-in-revit-api-pushbutton-pulldownbutton-splitbutton-radiobuttongroup\/#primaryimage"},"image":{"@id":"https:\/\/infralligence.com\/resources\/buttons-in-revit-api-pushbutton-pulldownbutton-splitbutton-radiobuttongroup\/#primaryimage"},"thumbnailUrl":"https:\/\/infralligence.com\/wp-content\/uploads\/2024\/12\/c1033987-201e-4d07-bb17-4e16a2eea21d.png","datePublished":"2024-09-04T08:43:44+00:00","dateModified":"2024-12-31T09:30:01+00:00","description":"Revit API offers several types of buttons: PushButton, PulldownButtons, SplitButtons, and RadioButtonGroups...","breadcrumb":{"@id":"https:\/\/infralligence.com\/resources\/buttons-in-revit-api-pushbutton-pulldownbutton-splitbutton-radiobuttongroup\/#breadcrumb"},"inLanguage":"pl-PL","potentialAction":[{"@type":"ReadAction","target":["https:\/\/infralligence.com\/resources\/buttons-in-revit-api-pushbutton-pulldownbutton-splitbutton-radiobuttongroup\/"]}]},{"@type":"ImageObject","inLanguage":"pl-PL","@id":"https:\/\/infralligence.com\/resources\/buttons-in-revit-api-pushbutton-pulldownbutton-splitbutton-radiobuttongroup\/#primaryimage","url":"https:\/\/infralligence.com\/wp-content\/uploads\/2024\/12\/c1033987-201e-4d07-bb17-4e16a2eea21d.png","contentUrl":"https:\/\/infralligence.com\/wp-content\/uploads\/2024\/12\/c1033987-201e-4d07-bb17-4e16a2eea21d.png"},{"@type":"BreadcrumbList","@id":"https:\/\/infralligence.com\/resources\/buttons-in-revit-api-pushbutton-pulldownbutton-splitbutton-radiobuttongroup\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/infralligence.com\/"},{"@type":"ListItem","position":2,"name":"Buttons in Revit API: PushButton, PulldownButton, SplitButton, RadioButtonGroup"}]},{"@type":"WebSite","@id":"https:\/\/infralligence.com\/#website","url":"https:\/\/infralligence.com\/","name":"Infralligence","description":"Digital Automation and AI for civil engineering","publisher":{"@id":"https:\/\/infralligence.com\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/infralligence.com\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"pl-PL"},{"@type":"Organization","@id":"https:\/\/infralligence.com\/#organization","name":"Infralligence","url":"https:\/\/infralligence.com\/","logo":{"@type":"ImageObject","inLanguage":"pl-PL","@id":"https:\/\/infralligence.com\/#\/schema\/logo\/image\/","url":"https:\/\/infralligence.com\/wp-content\/uploads\/2024\/11\/android-chrome-192x192-1.png","contentUrl":"https:\/\/infralligence.com\/wp-content\/uploads\/2024\/11\/android-chrome-192x192-1.png","width":192,"height":192,"caption":"Infralligence"},"image":{"@id":"https:\/\/infralligence.com\/#\/schema\/logo\/image\/"}},{"@type":"Person","@id":"https:\/\/infralligence.com\/#\/schema\/person\/838177275b7d3b8b217b13180a74aeda","name":"Kamil Korus","image":{"@type":"ImageObject","inLanguage":"pl-PL","@id":"https:\/\/infralligence.com\/#\/schema\/person\/image\/","url":"https:\/\/secure.gravatar.com\/avatar\/95bd7da2ac29ff34a2ab9bf4ea30273b?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/95bd7da2ac29ff34a2ab9bf4ea30273b?s=96&d=mm&r=g","caption":"Kamil Korus"},"sameAs":["https:\/\/www.linkedin.com\/in\/kamil-korus\/"],"url":"https:\/\/infralligence.com\/pl\/resources\/author\/kamil-korus\/"}]}},"_links":{"self":[{"href":"https:\/\/infralligence.com\/pl\/wp-json\/wp\/v2\/posts\/2727","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/infralligence.com\/pl\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/infralligence.com\/pl\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/infralligence.com\/pl\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/infralligence.com\/pl\/wp-json\/wp\/v2\/comments?post=2727"}],"version-history":[{"count":19,"href":"https:\/\/infralligence.com\/pl\/wp-json\/wp\/v2\/posts\/2727\/revisions"}],"predecessor-version":[{"id":2751,"href":"https:\/\/infralligence.com\/pl\/wp-json\/wp\/v2\/posts\/2727\/revisions\/2751"}],"wp:attachment":[{"href":"https:\/\/infralligence.com\/pl\/wp-json\/wp\/v2\/media?parent=2727"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/infralligence.com\/pl\/wp-json\/wp\/v2\/categories?post=2727"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/infralligence.com\/pl\/wp-json\/wp\/v2\/tags?post=2727"},{"taxonomy":"post_folder","embeddable":true,"href":"https:\/\/infralligence.com\/pl\/wp-json\/wp\/v2\/post_folder?post=2727"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}