How to create a dropdown in C#?
I have a list on enums:
public enum PanelType
{
Undefined,
Wall,
WallExternal,
WallInternal,
}
and trying to make a component that will allow user to select via the drop down… here is my GH script for the component below. Any help will be really appreciated
namespace SAM.Analytical.Grasshopper
{
public class AnalyticalPanelType : GH_Component
{
/// <summary>
/// Panel Type
/// </summary>
public AnalyticalPanelType()
: base("AnalyticalPanelType", "AnalyticalPanelType",
"Snap Panels",
"SAM", "Analytical")
{
}
public override bool AppendMenuItems(ToolStripDropDown menu)
{
base.AppendMenuItems(menu);
ToolStripDropDown toolStripDropDown = new ToolStripDropDown();
foreach (PanelType panelType in Enum.GetValues(typeof(PanelType)))
toolStripDropDown.Items.Add(panelType.ToString());
Control control = new Control();
global::Grasshopper.Kernel.GH_DocumentObject.Menu_AppendCustomItem(toolStripDropDown, control);
return true;
}
/// <summary>
/// Registers all the input parameters for this component.
/// </summary>
protected override void RegisterInputParams(GH_InputParamManager inputParamManager)
{
}
/// <summary>
/// Registers all the output parameters for this component.
/// </summary>
protected override void RegisterOutputParams(GH_OutputParamManager outputParamManager)
{
outputParamManager.AddGenericParameter("PanelType", "PanelType", "Analytical PanelType", GH_ParamAccess.item);
}
/// <summary>
/// This is the method that actually does the work.
/// </summary>
/// <param name="dataAccess">The DA object is used to retrieve from inputs and store in outputs.</param>
protected override void SolveInstance(IGH_DataAccess dataAccess)
{
}
/// <summary>
/// Provides an Icon for the component.
/// </summary>
protected override System.Drawing.Bitmap Icon
{
get
{
//You can add image files to your project resources and access them like this:
// return Resources.IconForThisComponent;
return Resources.HL_Logo24;
}
}
/// <summary>
/// Gets the unique ID for this component. Do not change this ID after release.
/// </summary>
public override Guid ComponentGuid
{
get { return new Guid("25a6b405-19ab-4ff1-9666-7760997ccfdd"); }
}
}
}
namespace SAM.Analytical.Grasshopper
{
public class AnalyticalPanelType : GH_Component
{
private PanelType panelType = PanelType.Undefined;
/// <summary>
/// Panel Type
/// </summary>
public AnalyticalPanelType()
: base("AnalyticalPanelType", "AnalyticalPanelType",
"Snap Panels",
"SAM", "Analytical")
{
}
public override bool Write(GH_IWriter writer)
{
writer.SetInt32("PanelType", (int)panelType);
return base.Write(writer);
}
public override bool Read(GH_IReader reader)
{
int aIndex = -1;
if (reader.TryGetInt32("PanelType", ref aIndex))
panelType = (PanelType)aIndex;
return base.Read(reader);
}
protected override void AppendAdditionalComponentMenuItems(ToolStripDropDown menu)
{
foreach (PanelType panelType in Enum.GetValues(typeof(PanelType)))
GH_Component.Menu_AppendItem(menu, panelType.ToString(), Menu_PanelTypeChanged).Tag = panelType;
base.AppendAdditionalComponentMenuItems(menu);
}
private void Menu_PanelTypeChanged(object sender, EventArgs e)
{
if (sender is ToolStripMenuItem item && item.Tag is PanelType)
{
//Do something with panelType
this.panelType = (PanelType)item.Tag;
ExpireSolution(true);
}
}
/// <summary>
/// Registers all the input parameters for this component.
/// </summary>
protected override void RegisterInputParams(GH_InputParamManager inputParamManager)
{
}
/// <summary>
/// Registers all the output parameters for this component.
/// </summary>
protected override void RegisterOutputParams(GH_OutputParamManager outputParamManager)
{
outputParamManager.AddGenericParameter("PanelType", "PanelType", "Analytical PanelType", GH_ParamAccess.item);
}
/// <summary>
/// This is the method that actually does the work.
/// </summary>
/// <param name="dataAccess">The DA object is used to retrieve from inputs and store in outputs.</param>
protected override void SolveInstance(IGH_DataAccess dataAccess)
{
dataAccess.SetData(0, panelType);
}
/// <summary>
/// Provides an Icon for the component.
/// </summary>
protected override System.Drawing.Bitmap Icon
{
get
{
//You can add image files to your project resources and access them like this:
// return Resources.IconForThisComponent;
return Resources.HL_Logo24;
}
}
/// <summary>
/// Gets the unique ID for this component. Do not change this ID after release.
/// </summary>
public override Guid ComponentGuid
{
get { return new Guid("25a6b405-19ab-4ff1-9666-7760997ccfdd"); }
}
}
}
@michaldengusiak this post is really useful! When I am defining the panelType variable I got the error that PanelType does not contain Undefined. Do you think it is a problem with the references? Any advice?
using System;
using System.Collections.Generic;
using System.Windows.Forms;
using GH_IO.Serialization;
using Grasshopper.Kernel;
using Rhino.Geometry;
using Rhino.UI;
namespace ExtendingGUIList
{
public class DropDownExample : GH_Component
{
private PanelType panelType = PanelType.Undefined;
/// <summary>
/// Initializes a new instance of the DropDownExample class.
/// </summary>
public DropDownExample()
: base("DropDownExample", "Nickname",
"Description",
"AIOS", "Subcategory")
{
}
public override bool Write(GH_IWriter writer)
{
writer.SetInt32("PanelType", (int)panelType);
return base.Write(writer);
}
public override bool Read(GH_IReader reader)
{
int aIndex = -1;
if (reader.TryGetInt32("PanelType", ref aIndex))
panelType = (PanelType)aIndex;
return base.Read(reader);
}
protected override void AppendAdditionalComponentMenuItems(ToolStripDropDown menu)
{
foreach (PanelType panelType in Enum.GetValues(typeof(PanelType)))
GH_Component.Menu_AppendItem(menu, panelType.ToString(), Menu_PanelTypeChanged).Tag = panelType;
base.AppendAdditionalComponentMenuItems(menu);
}
private void Menu_PanelTypeChanged(object sender, EventArgs e)
{
if (sender is ToolStripMenuItem item && item.Tag is PanelType)
{
//Do something with panelType
this.panelType = (PanelType)item.Tag;
ExpireSolution(true);
}
}
/// <summary>
/// Registers all the input parameters for this component.
/// </summary>
protected override void RegisterInputParams(GH_Component.GH_InputParamManager pManager)
{
}
/// <summary>
/// Registers all the output parameters for this component.
/// </summary>
protected override void RegisterOutputParams(GH_Component.GH_OutputParamManager pManager)
{
pManager.AddGenericParameter("PanelType", "PanelType", "PanelType is the best", GH_ParamAccess.item);
}
/// <summary>
/// This is the method that actually does the work.
/// </summary>
/// <param name="DA">The DA object is used to retrieve from inputs and store in outputs.</param>
protected override void SolveInstance(IGH_DataAccess DA)
{
}
/// <summary>
/// Provides an Icon for the component.
/// </summary>
protected override System.Drawing.Bitmap Icon
{
get
{
//You can add image files to your project resources and access them like this:
// return Resources.IconForThisComponent;
return null;
}
}
/// <summary>
/// Gets the unique ID for this component. Do not change this ID after release.
/// </summary>
public override Guid ComponentGuid
{
get { return new Guid("7C82C338-CB29-4544-B3BC-5463DDB0CE65"); }
}
}
}
hello, I had the same issue; replying late should it help others he’s the solution:
You’ve forgotten to add the enumerated list object in Michal’s original post, add this code:
public enum PanelType
{
Undefined,
Wall,
WallExternal,
WallInternal,
}
Note, PanelType is the name of the Rhino.UI object type and is a keyword from the API.
panelType is the chosen name for the object created from the new constructor by the author. (hint: edit this name)