C# Dropdown

I’m trying to make this code work, but I cannot find this RevitDropDownBase class, that has to be inherited from. Where is this class from or what reference do I have to add to get access to it?

I tried searching on the this forum, also on the Dynamo repository on github, but there’s not a single hit anywhere but this thread.

After digging a bit deeper I found that all those classes inherit from the DSDropDownBase class, but I still cannot make this work correctly.

If the constructur is commented out (I found this by accident) I can almost get the GUI working with the options shown in the dropdown, however the node throws an error. If the constructor is in the code, the node does not show up in Dynamo at all. Does anyone have a clue what I’m doing wrong there?

public class DummyDropdown : DSDropDownBase
{
    //Only if comment this line out, does the node show up in Dynamo but does not work.
    protected DummyDropdown() : base("Selection") { }

    protected override SelectionState PopulateItemsCore(string currentSelection)
    {
        Items.Clear();
        Dictionary<string, int> dropdownItems = new Dictionary<string, int> {
            { "Test1", 1 },
            { "Test2", 2 },
            { "Test3", 3 },
            { "Test4", 4 },
        };
        foreach (KeyValuePair<string, int> item in dropdownItems)
        {
            Items.Add(new DynamoDropDownItem(item.Key, item.Value));
        }
        return SelectionState.Restore;
    }

    public override IEnumerable<AssociativeNode> BuildOutputAst(List<AssociativeNode> inputAstNodes)
    {
        return new[] { AstFactory.BuildAssignment(GetAstIdentifierForOutputIndex(0), AstFactory.BuildIntNode((int)(Items[SelectedIndex].Item))) };
    }
}

you can’t import UI nodes via zero touch (as far as I know) - these are nodes which inherit directly from NodeModel and need to be imported as part of a package or from the dynamo nodes folder.

I think there was just a discussion where @Konrad_K_Sobon showed how to do this with a revit class pretty simply.

1 Like

Yeah, it was answered here: C# Dynamo Nodes - Dropdown input Node

1 Like

Yes, I initially replied to the same thread you are reffering to and asked for a bit more help, but an admin split my replies into this thread.

I think it makes sense to inherit from the more generic DSDropDownBase, because I’m trying to get some very specific behaviour (only show Revit Model Groups that have a name matching a RegEx and update if something changes about the groups content). I’m quite sure I can figure out the rest, if I get this dropdown working.

I figured it out now. It is important that the BuildOutputAst is able to return a null node, in case the SelectedIndex is -1. Also had to make constructor public (Can’t understand how I missed it earlier :smiley: ). This is the code that works:

public class DummyDropdown : DSDropDownBase
{
    public DummyDropdown() : base("Name of the output") { }

    protected override SelectionState PopulateItemsCore(string currentSelection)
    {
        Items.Clear();
        Dictionary<string, int> dropdownItems = new Dictionary<string, int> {
            { "Test1", 1 },
            { "Test2", 2 },
            { "Test3", 3 },
            { "Test4", 4 },
        };
        foreach (KeyValuePair<string, int> item in dropdownItems)
        {
            Items.Add(new DynamoDropDownItem(item.Key, item.Value));
        }
        return SelectionState.Restore;
    }

    public override IEnumerable<AssociativeNode> BuildOutputAst(List<AssociativeNode> inputAstNodes )
    {
        if (Items.Count == 0 ||
            SelectedIndex == -1) //NB! This line is crucial for some reason
        {
            return new[] { AstFactory.BuildAssignment(GetAstIdentifierForOutputIndex(0), AstFactory.BuildNullNode()) };
        }

        var intNode = AstFactory.BuildIntNode((int)Items[SelectedIndex].Item);
        var assign = AstFactory.BuildAssignment(GetAstIdentifierForOutputIndex(0), intNode);
        return new List<AssociativeNode> { assign };
    }
}
4 Likes

Do you have an example VS project maybe?

Or a list of references needed for this. I try to create a dropdown node but it won’t show the dropdown part…

@Anton_Huizinga, i think you have to load your dll through a package. See the attached post;

It would be bizarre if such workarounds solve the case.

So I tried, I created a Package with Dynamo, so I could not make mistakes in the file or folder structure.

Now Dynamo does load the package, it is shown in the Manage Package list as loaded, it does not show any errors, but the whole package is not shown in the categories!

When I manually load the same DLL, it does show in the category list but without the proper dropdown node.

Why? It shouldn’t be that hard to create Zero Touch nodes with a dropdown :confused:

hi @Anton_Huizinga, create a folder containing " bin folder & pkg.json file ". In pkg.json file add the following json data and put your dll in the bin folder.

{

  "license": "MIT",

  "file_hash": null,

  "name": "YourPackageName",

  "version": "1.0.0",

  "description": "Package for testing.",

  "group": "revit",

  "keywords": [],

  "dependencies": [],

  "contents": "",

  "engine_version": "2.5.0",

  "engine": "dynamo",

  "engine_metadata": "",

  "site_url": "",

  "repository_url": "",

  "contains_binaries": true,

  "node_libraries":

    "YourPackageDLLFile, Version=1.0.0, Culture=neutral, PublicKeyToken=null"

}

That is what I did.

Next week I’ll create a test project and try do find out what is wrong. To be continued…

“Next week” was a bit optimistic but finally I was able to do some testing. And I got result.

There are two things you should know:

  1. It seems not possible to combine UI and Zero Touch nodes in one DLL so you need to use a seperate Solution to build dropdown nodes.

  2. It only works if the DLL is loaded via a package, not with the ‘import library’ function.

You can download a sample Visual Studio Solution below (without de compiled DLL file). Two classes are available. One to create a dropdown that returns the name of a Tin Surface as a string and one to create a dropdown that outputs the Tin Surface as object. In Dynamo it looks like this:

After building a release DLL you need to create a package, you can do via de Dynamo Package menu:

Do publish locally, not online! After that the dropdown nodes appear in the category list.

You can download the sample code here:

Sample code, VS Solution, no DLL, zipped

Good luck and happy coding! Hope it will help someone!

3 Likes

Hi @Anton_Huizinga thanks for this work! If you have any suggestions on how we could improve the DynamoSamples to better illustrate making dropdowns please add an issue or pr there! One complexity is that this repo needs to work without any host - but data can be mocked of course.

Hi everyone,
I’m trying to create a dropdown for Revit 2023, Dynamo Version 2.16.1. I took the example “DropDown” from the DynamoDS/DynamoSamples repository, updated references, did small changes in the code and launched it Dynamo. But the nodes don’t display any dropdowns… Here is the code.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using CoreNodeModels;
using Dynamo.Graph.Nodes;
using Dynamo.Utilities;
using ProtoCore.AST.AssociativeAST;
using Newtonsoft.Json;
using System.Collections.ObjectModel;

namespace Test_dropdown
{
    [NodeName("Drop Down Example")]
    [NodeDescription("An example drop down node.")]
    [IsDesignScriptCompatible]
    public class DropDownExample : DSDropDownBase
    {
        public DropDownExample() : base("item") { }

        [JsonConstructor]
        public DropDownExample(IEnumerable<PortModel> inPorts, IEnumerable<PortModel> outPorts) : base("item", inPorts, outPorts) { }

        protected override SelectionState PopulateItemsCore(string currentSelection)
        {

            Items.Clear();


            var newItems = new List<DynamoDropDownItem>()
            {
                new DynamoDropDownItem("Tywin", 0),
                new DynamoDropDownItem("Cersei", 1),
                new DynamoDropDownItem("Hodor",2)
            };

            Items = new ObservableCollection<DynamoDropDownItem>(newItems);


            SelectedIndex = 0;
            return SelectionState.Restore;
        }

        public override IEnumerable<AssociativeNode> BuildOutputAst(List<AssociativeNode> inputAstNodes)
        {

            var intNode = AstFactory.BuildPrimitiveNodeFromObject(Items[SelectedIndex].Item);
            var assign = AstFactory.BuildAssignment(GetAstIdentifierForOutputIndex(0), intNode);

            return new List<AssociativeNode> { assign };
        }
    }
}

I also tried other examples. For instance, this one – Lisa-Marie Mueller | Lastest Posts, with inheritance from the RevitDropDownBase. The most strange thing by this example, I started to test this example on Friday 17.03 and I saw a dropdown. But on Monday (20.03) it disappeared.

At the same time the other nodes (which were earlier compiled with dropdowns) from third party packages are working in Dynamo.

I think, possible problems are:

  • There are mistakes in my code
  • Something was broken in Dynamo in the recent update

All help is appreciated,

Thanks

Dina
image

it looks like you are importing the assembly as a zero touch package - UI nodes don’t work like that - import the resulting DynamoSamples package - not the assembly.

(see the discussion above)

1 Like

Thanks a lot :slightly_smiling_face: It helped

1 Like