Problem with DropDown

Hello everyone, I just created a drop down button that works all the time, but when I pinned a button, an error occurred to me, below is the error code and video, please give me advice.The drop down button with other functions I still work normally , and if you have a way to debug code in dynamo with C#, please share it with me, thanks a lot.

This is my code

    [NodeName("DuctTypes")]
    [NodeCategory("MEP.Ducts")]
    [NodeDescription("Get All Duct Type From Model Dropdown")]
    [IsDesignScriptCompatible]
    public class DuctTypeUi : DSDropDownBase
    {
        const string NoDuctTypes = "No types were found.";

        /// <summary>
        /// </summary>
        public DuctTypeUi() : base("DuctType")
        {
        }

        /// <summary>
        /// </summary>
        /// <param name="currentSelection"></param>
        /// <returns></returns>
        protected override SelectionState PopulateItemsCore(string currentSelection)
        {
            Items.Clear();

            Document doc = DocumentManager.Instance.CurrentDBDocument;
            List<Element> vtList = new FilteredElementCollector(doc).OfClass(typeof(DuctType)).ToList();

            if (vtList.Count == 0)
            {
                Items.Add(new DynamoDropDownItem(NoDuctTypes, null));
                SelectedIndex = 0;
                return SelectionState.Done;
            }

            foreach (DuctType v in vtList) Items.Add(new DynamoDropDownItem(v.Name, v));
            Items = Items.OrderBy(x => x.Name).ToObservableCollection();
            return SelectionState.Restore;
        }

        /// <summary>
        /// </summary>
        /// <param name="inputAstNodes"></param>
        /// <returns></returns>
        public override IEnumerable<AssociativeNode> BuildOutputAst(List<AssociativeNode> inputAstNodes)
        {
            AssociativeNode node;

            if (SelectedIndex == -1)
            {
                node = AstFactory.BuildNullNode();
            }
            else
            {
                DuctType ductType = Items[SelectedIndex].Item as DuctType;


                StringNode idNode = AstFactory.BuildStringNode(ductType.UniqueId);
                BooleanNode falseNode = AstFactory.BuildBooleanNode(true);

                node = AstFactory.BuildFunctionCall(
                    new Func<string, bool, object>(ElementSelector.ByUniqueId),
                    new List<AssociativeNode> {idNode, falseNode});
            }

            return new[] {AstFactory.BuildAssignment(GetAstIdentifierForOutputIndex(0), node)};
        }
    }
}

first thing first, since you are doing a revit drop down, and not dynamo drop down. I believe you should use the RevitDropDownBase instead of DSDropDownBase as your inherits.

Secondly, always dispose any garbage collection in your code unless you want your dynamo to get choked up by those collection, garbage collection like FilteredElementCollector and maybe Element(?). So if i were you, i would use element.Id.IntegerValue and element.Name and collect them in a dictionary before sending it out the ObservableCollection(). For example:

Dictionary<string,int> dropdownitems = new Dictionary<string,int>();
using(FilteredElementCollector col = new FilteredElementCollector(doc).OfClass(typeof(DuctType)))
{
    foreach(Element ele in col)
        dropdownitems.Add(ele.Name, ele.Id.IntegerValue)
}
if (dropdownitems.Count == 0)
{
    Items.Add(new DynamoDropDownItem(NoDuctTypes, null));
    SelectedIndex = 0;
    return SelectionState.Done;
}
Items.Clear();    
Items = dropdownitems.Select(x => new DynamoDropDownItem(x.Key,x.Value)).OrderBy(x => x.Key).ToObservableCollection();
return SelectionState.Restore;

Then use the dynamo’s builtin Revit.Elements.ElementSelector.ByElementId method to retrieve the dynamo element in your BuildOutputAst method.

I am working with dynamo 2.0 and it doesn’t seem to have RevitDropDownBase !

you will need to reference from DSRevitNodesUI assembly.

image

It is still not possible to solve my problem, thanks for your answer.

do you mind showing the updated code?? the same error occurs? that is weird…

When I add the DSRevitNodesUI library, the same error occurs, currently I am working on Revit 2020
image


The ‘+’ character, hexadecimal value 0x2B, cannot be included in a name.

at System.Xml.XmlDocument.CheckName(String name)
at System.Xml.XmlElement…ctor(XmlName name, Boolean empty, XmlDocument doc)
at System.Xml.XmlDocument.CreateElement(String prefix, String localName, String namespaceURI)
at System.Xml.XmlDocument.CreateElement(String name)
at Dynamo.Graph.ModelBase.CreateElement(XmlDocument xmlDocument, SaveContext context)
at Dynamo.Core.UndoRedoRecorder.RecordActionInternal(XmlElement group, ModelBase model, UserAction action)
at Dynamo.Core.UndoRedoRecorder.ModelModificationUndoHelper…ctor(UndoRedoRecorder recorder, IEnumerable1 models) at Dynamo.Graph.Workspaces.WorkspaceModel.UpdateModelValue(IEnumerable1 modelGuids, String propertyName, String value)
at Dynamo.Models.DynamoModel.UpdateModelValueImpl(UpdateModelValueCommand command)
at Dynamo.Models.DynamoModel.ExecuteCommand(RecordableCommand command)
at Dynamo.ViewModels.NodeViewModel.set_PreviewPinned(Boolean value)
at Dynamo.UI.Controls.PreviewControl.OnMapPinMouseClick(Object sender, MouseButtonEventArgs e)
at System.Windows.RoutedEventArgs.InvokeHandler(Delegate handler, Object target)
at System.Windows.RoutedEventHandlerInfo.InvokeHandler(Object target, RoutedEventArgs routedEventArgs)
at System.Windows.EventRoute.InvokeHandlersImpl(Object source, RoutedEventArgs args, Boolean reRaised)
at System.Windows.UIElement.ReRaiseEventAs(DependencyObject sender, RoutedEventArgs args, RoutedEvent newEvent)
at System.Windows.UIElement.OnMouseDownThunk(Object sender, MouseButtonEventArgs e)
at System.Windows.RoutedEventArgs.InvokeHandler(Delegate handler, Object target)
at System.Windows.RoutedEventHandlerInfo.InvokeHandler(Object target, RoutedEventArgs routedEventArgs)
at System.Windows.EventRoute.InvokeHandlersImpl(Object source, RoutedEventArgs args, Boolean reRaised)
at System.Windows.UIElement.RaiseEventImpl(DependencyObject sender, RoutedEventArgs args)
at System.Windows.UIElement.RaiseTrustedEvent(RoutedEventArgs args)
at System.Windows.Input.InputManager.ProcessStagingArea()
at System.Windows.Input.InputManager.ProcessInput(InputEventArgs input)
at System.Windows.Input.InputProviderSite.ReportInput(InputReport inputReport)
at System.Windows.Interop.HwndMouseInputProvider.ReportInput(IntPtr hwnd, InputMode mode, Int32 timestamp, RawMouseActions actions, Int32 x, Int32 y, Int32 wheel)
at System.Windows.Interop.HwndMouseInputProvider.FilterMessage(IntPtr hwnd, WindowMessage msg, IntPtr wParam, IntPtr lParam, Boolean& handled)
at System.Windows.Interop.HwndSource.InputFilterMessage(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam, Boolean& handled)
at MS.Win32.HwndWrapper.WndProc(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam, Boolean& handled)
at MS.Win32.HwndSubclass.DispatcherCallbackOperation(Object o)
at System.Windows.Threading.ExceptionWrapper.InternalRealCall(Delegate callback, Object args, Int32 numArgs)
at System.Windows.Threading.ExceptionWrapper.TryCatchWhen(Object source, Delegate callback, Object args, Int32 numArgs, Delegate catchHandler)

can show the code as well?? cause i cant reproduce the same error from my side

DuctTypeModel.txt (2.6 KB)
Here’s the code in my class.

[NodeName("DuctTypes")]
[NodeCategory("DynaMEP.DynaMEP.MEP.Ducts")]
[NodeDescription("Get All Duct Type From Model Dropdown")]
[IsDesignScriptCompatible]
public class DuctTypeModel : RevitDropDownBase
{
    const string NoDuctTypes = "No Duct Types Found.";

    public DuctTypeModel() : base("DuctType")
    {

    }

    [Newtonsoft.Json.JsonConstructor]
    public DuctTypeModel(IEnumerable<PortModel> inports, IEnumerable<PortModel> outports) : base("DuctType", inports, outports)
    {

    }

    protected override SelectionState PopulateItemsCore(string currentSelection)
    {
        Dictionary<string, int> dropdownitems = new Dictionary<string, int>();
        using (Document doc = DocumentManager.Instance.CurrentDBDocument)
        using (FilteredElementCollector col = new FilteredElementCollector(doc).OfClass(typeof(DuctType)))
        {
            foreach (Autodesk.Revit.DB.Element ele in col)
                dropdownitems.Add(ele.Name, ele.Id.IntegerValue);
        }

        if (dropdownitems.Count == 0)
        {
            Items.Add(new DynamoDropDownItem(NoDuctTypes, null));
            SelectedIndex = 0;
            return SelectionState.Done;
        }
        Items.Clear();
        Items = dropdownitems.Select(x => new DynamoDropDownItem(x.Key, x.Value)).OrderBy(x => x.Name).ToObservableCollection();
        return SelectionState.Restore;
    }

    public override IEnumerable<AssociativeNode> BuildOutputAst(List<AssociativeNode> inputAstNodes)
    {
        if (Items.Count == 0 || SelectedIndex == -1 || Items[0].Name == NoDuctTypes)
        {
            return new[] { AstFactory.BuildAssignment(GetAstIdentifierForOutputIndex(0), AstFactory.BuildNullNode()) };
        }

        Func<int, bool, Revit.Elements.Element> callfunction = new Func<int, bool, Revit.Elements.Element>(ElementSelector.ByElementId);
        AssociativeNode selectId = AstFactory.BuildIntNode((int)Items[SelectedIndex].Item);
        AssociativeNode isRevitOwned = AstFactory.BuildBooleanNode(false);

        AssociativeNode callFunctionNode = AstFactory.BuildFunctionCall(
            callfunction,
            new List<AssociativeNode>
            {
                selectId,isRevitOwned
            });

        BinaryExpressionNode assign1 = AstFactory.BuildAssignment(GetAstIdentifierForOutputIndex(0), callFunctionNode);

        return new[]
        {
            assign1
        };
    }
}

this should do the trick. and you didnt even make changes to the one i told you about…

I work with your new code, it shows the node name but I do not click to display that node to the main screen.

i honestly have no idea to help you with that, the error is new to me too.


the underlined error is the error that is causing the node to not appear.

1 Like

I thank you so much for help, I will continue to look for solutions to this error. I hope someone will find the solution.

[NodeName("Wall Types")]
[NodeCategory(BuiltinNodeCategories.REVIT_SELECTION)]
[NodeDescription("WallTypesDescription", typeof(Properties.Resources))]
[IsDesignScriptCompatible]
public class WallTypes : RevitDropDownBase
{
    private const string outputName = "Wall Type";

    public WallTypes() : base(outputName) { }

    [JsonConstructor]
    public WallTypes(IEnumerable<PortModel> inPorts, IEnumerable<PortModel> outPorts) : base(outputName, inPorts, outPorts) { }

    protected override SelectionState PopulateItemsCore(string currentSelection)
    {
        Items.Clear();

        var fec = new FilteredElementCollector(DocumentManager.Instance.CurrentDBDocument);

        fec.OfClass(typeof(Autodesk.Revit.DB.WallType));
        var elements = fec.ToElements();
        if (!elements.Any())
        {
            Items.Add(new DynamoDropDownItem(Properties.Resources.NoWallTypesAvailable, null));
            SelectedIndex = 0;
            return SelectionState.Done;
        }

        Items = elements.Select(x => new DynamoDropDownItem(x.Name, x)).OrderBy(x => x.Name).ToObservableCollection();
        return SelectionState.Restore;
    }

    public override IEnumerable<AssociativeNode> BuildOutputAst(List<AssociativeNode> inputAstNodes)
    {
        if(!CanBuildOutputAst(Properties.Resources.NoWallTypesAvailable))
            return new[] { AstFactory.BuildAssignment(GetAstIdentifierForOutputIndex(0), AstFactory.BuildNullNode()) };
        
        var args = new List<AssociativeNode>
        {
            AstFactory.BuildStringNode(((Autodesk.Revit.DB.WallType) Items[SelectedIndex].Item).Name)
        };
        var functionCall = AstFactory.BuildFunctionCall("Revit.Elements.WallType",
                                                        "ByName",
                                                        args);

        return new[] { AstFactory.BuildAssignment(GetAstIdentifierForOutputIndex(0), functionCall) };
    }
}

If you look at DynamoRevit Souce code, what they provided is similar to what i had done for you. So honestly, i have no idea whats wrong too?

I found a problem like me here but I do not see what is the solution.I Hope @Konrad_K_Sobon Can help me ! https://github.com/DynamoDS/Dynamo/issues/5120

okay i have found out my mistake… It was the dictionary issue…
heres the code:

[NodeName("Duct Types")]
[NodeDescription("Get All Duct Type From Model Dropdown")]
[NodeCategory("DynaMEP.MEP.Ducts")]
[IsDesignScriptCompatible]
public class DuctTypes : RevitDropDownBase
{
    private const string outPutName = "Duct Type";
    private const string NO_DUCT_TYPES = "No Duct Types Found.";

    public DuctTypes() : base(outPutName) { }

    [JsonConstructor]
    public DuctTypes(IEnumerable<PortModel> inPorts, IEnumerable<PortModel> outPorts) : base(outPutName, inPorts, outPorts) { }

    protected override SelectionState PopulateItemsCore(string currentSelection)
    {
        Items.Clear();

        Dictionary<int, string> eleNameInt = new Dictionary<int, string>();
        
        using (FilteredElementCollector col = new FilteredElementCollector(DocumentManager.Instance.CurrentDBDocument).OfClass(typeof(DuctType)))
        {
            var eles = col.ToElements();
            if (!eles.Any())
            {
                Items.Add(new DynamoDropDownItem(NO_DUCT_TYPES, null));
                SelectedIndex = 0;
                return SelectionState.Done;
            }
            foreach (var ele in eles)
                eleNameInt.Add(ele.Id.IntegerValue,  ele.Name);
        }

        Items = eleNameInt.Select(x => new DynamoDropDownItem(x.Value, x.Key)).OrderBy(x => x.Name).ToObservableCollection();
        return SelectionState.Restore;
    }

    public override IEnumerable<AssociativeNode> BuildOutputAst(List<AssociativeNode> inputAstNodes)
    {
        if (!CanBuildOutputAst(NO_DUCT_TYPES))
            return new[] { AstFactory.BuildAssignment(GetAstIdentifierForOutputIndex(0), AstFactory.BuildNullNode()) };

        List<AssociativeNode> args = new List<AssociativeNode>()
        {
            AstFactory.BuildIntNode((int)Items[SelectedIndex].Item),
            AstFactory.BuildBooleanNode(true),
        };

        Func<System.Int32, System.Boolean, Revit.Elements.Element> func = new Func<System.Int32, System.Boolean, Revit.Elements.Element>(Revit.Elements.ElementSelector.ByElementId);

        AssociativeNode callFunctionNode = AstFactory.BuildFunctionCall<System.Int32, System.Boolean, Revit.Elements.Element>(
            Revit.Elements.ElementSelector.ByElementId,
            args
            );

        BinaryExpressionNode assign1 = AstFactory.BuildAssignment(GetAstIdentifierForOutputIndex(0), callFunctionNode);

        return new[]
        {
            assign1
        };

        bool CanBuildOutputAst(string itemValueToIgnore = null, string selectedValueToIgnore = null)
        {
            if (Items.Count == 0 || SelectedIndex < 0)
                return false;
            if (!string.IsNullOrEmpty(itemValueToIgnore) && Items[0].Name == itemValueToIgnore)
                return false;
            if (!string.IsNullOrEmpty(selectedValueToIgnore) && Items[SelectedIndex].Name == selectedValueToIgnore)
                return false;
            return true;
        }
    }
}


I tried with your new code but the error is still happening
image

what is the namespace you are using?? Mostly is that you have accidentally concat strings together and formed an illegal character “+” somewhere along the line.

Im using with name

DynaMEPUI.Duct

Have Problem ?

for explicit node, dont think there is a need for having “.” in your namepsace, unless you have a really huge class? Possible to show me the entire class? does this error only happens at that node?