Navisworks API : Search ModelItem and Collect Properties

Welcome to the second tutorial of Navisworks® API series, this post is to cover how to Search ModelItem & collect ModelItem Properties. The task is ” to find a ModelItem by its Id and collect the properties data of ModelItem‘s Element category. “

Demo – Search & Properties

As usual, let’s start our project by setting up Navisworks® Add-Ins project in the visual studio, you can follow Creating Navisworks Add-Ins tutorial to set up the project. Whenever you are ready, in MainClass.Execute method create two variables; Document doc to store the current Document and StringBuilder message to store the display string. (figure 1.1)

figure 1.1 – Variables & Form

Create a simple Form object for user input and one more variable, int Id, to store SearchBox return value (ModelItemId). try-catch statement is to handles error of user input during the conversion to integer value. (figure 1.2)

figure 1.2 – SearchBox Form

In the SearchBox Form partial class, create a public property named ReturnValue, to store & return user input Id value. (figure 1.3)

figure 1.3 – SearchBox partial class

Back to MainClass.Execute method, create a Search object to runs to find ModelItem by its Id. There are a couple of methods in SearchCondition class, here we uses SearchCondition.HasPropertyByDisplayName method which create a condition that matches if item has category with specified DisplayName (figure 1.4). Additionally, to understand better, you can uses the InternalName or CombineName too. In figure 1.4a, show SearchCondition.HasPropertyByName method by InternalName.

figure 1.4 – Search by Display Name
figure 1.4a – Search by Internal Name

Let’s take one more step for solid understanding, in the figure 1.5, as you can see the relation of Navisworks® Find Items user interface and our Search object code.

figure 1.5 – Search UI vs API

After we found the ModelItem via Search, the next step is to collect a specific Category of the ModelItem‘s properties data. First, select this ModelItem by using doc.CurrentSelection.Add method. Next, to find ModelItem‘s Element PropertyCategory object by using FindCategoryByDisplayName method. From PropertyCategory object, we can collect DataPropertyCollection which includes all the properties data of a specific Category, in this case, Element Category. Add total number of properties to message as the first line of code to display. (figure 1.6)

figure 1.6 – Properties Data

Iterate the properties, fetch property’s DisplayName & Value from the DataProperty and add to the message. And finally, display the message via WindowForms's MessageBox and mandatory return an int value.

That’s the end of our tutorial, the Execute method code is below & you can download the complete project source code from here. Cheers!

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

using wf = System.Windows.Forms;
using Autodesk.Navisworks.Api;
using Autodesk.Navisworks.Api.Plugins;
using Autodesk.Navisworks.Api.DocumentParts;


namespace Lab5_Exercise
{
    [PluginAttribute("Lab5_Exec", "TwentyTwo",DisplayName = "Lab5_Exec", ToolTip = "Lab5_exercise project")]

    public class MainClass : AddInPlugin
    {
        // implement execute method 
        public override int Execute(params string[] parameters)
        {         
            // current document
            Document doc = Application.ActiveDocument;
            // display message
            StringBuilder message = new StringBuilder();

            // SearchBox form
            SearchBox sb = new SearchBox();
            // show form
            sb.ShowDialog();
            // assign Id value
            int Id = 0;

            try
            {
                // convert sb return value string to int
                Id = Convert.ToInt32(sb.ReturnValue);
            }
            catch { }

            // create search object
            Search search = new Search();
            // selection to search
            search.Selection.SelectAll();

             // create SearchCondition by InternalName of Category & Property
             // to find the specific item by its ID
            SearchCondition condition = SearchCondition.HasPropertyByName("LcRevitData_Element",
                 "LcRevitPropertyElementId").EqualValue(new VariantData(Id));
 
            /*
            // create SearchCondition by DisplayName of Category & Property
            // to find the specific item by its ID
            SearchCondition condition = SearchCondition.HasPropertyByDisplayName("Element",
                "Id").EqualValue(new VariantData(Id));
           */

            // SearchCondition to applied during search
            search.SearchConditions.Add(condition);
            // collect model item (if found)
            ModelItem item = search.FindFirst(doc,false);

            // item found
            if (item != null)
            {
                // make selection
                doc.CurrentSelection.Add(item);
                // get modelitem's Element category by display name method
                PropertyCategory elementCategory = item.PropertyCategories.
                    FindCategoryByDisplayName("Element");
                // all properties of Element category
                DataPropertyCollection dataProperties = elementCategory.Properties;               
                // display properties count 
                message.Append(String.Format("[{0}] ModelItem's Element Category has {1} Properties.\n",
                    Id.ToString(), dataProperties.Count));
                // index
                int index = 1;
                // iterate properties
                foreach (DataProperty dp in elementCategory.Properties)
                {
                    // append to display "Property Display Name & Property Value(includes DataType)"
                    message.Append(String.Format("{0}. {1} => {2}\n", index, dp.DisplayName, dp.Value));
                    // index increment
                    index += 1;
                    
                }
                // display message
                wf.MessageBox.Show(message.ToString(), "Element Category");
            }
            // return value
            return 0;          
        }

    }
}

Responses to “Navisworks API : Search ModelItem and Collect Properties”

  1. Xero Avatar
    Xero

    Thank you for these great tutorials! FYI I am having trouble recognizing SearchBox. Where is the reference for this?

    Like

    1. min.naung Avatar

      Hi Xero, thanks. SearchBox is a custom winform that was just created for user input.

      Like

  2. Xero Avatar
    Xero

    Disregard my question. Somehow I skipped an entire section in the tutorial.

    Like

    1. min.naung Avatar

      Hahaha … 👍

      Like

  3. Camne Avatar
    Camne

    Hi,
    thanks for these tutorials!
    Is there way you can search and select multiple elements by ID? (how to put that in code?)
    Is there a way you can look for elements by a parameter different thant ID (like name or Revit Parameter?)

    Like

  4. min.naung Avatar

    Hi Camne, thank a lot for your donation. I haven’t seen any method for searching multi IDs but may be you can take a look at these for search conditions sample: https://apidocs.co/apps/navisworks/2018/T_Autodesk_Navisworks_Api_SearchConditionCollection.htm

    And i have a tutorial on accessing parameters : https://twentytwo.space/2020/07/18/navisworks-api-com-interface-and-adding-custom-property/

    Like

  5. Văn Quyết Avatar
    Văn Quyết

    Hi Min.Naung, I just replace the code that selects elementid with the following code, and it always throws the “object reference not set to an instance of an object” error. I want to loop through all the objects in naviswork

    //Select the all item
    var all = doc.Models.CreateCollectionFromRootItems().SelectMany(m => m.DescendantsAndSelf).ToList();

    var item = all[0];
    // item found

    Like

Leave a comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.