0

I have written quite a few different add-ins now but I keep struggling to get a windows form working on Revit. The program builds fine and I have the dll set up for Revit to access.

Here are the different sections of my code. The program is more extensive than what is seen but I believe that the problem is a reference issue or a problem with my ADDIN file. Maybe there is a different way I need to set up my ADDIN file since I have a windows form in it?? Let me know.

Here is a Dropbox folder with the screenshots in it.

Let me know if there is anything else you need to see. The error in Revit says it has to do with the FullName but I believe I put it in the ADDIN file correctly, and I did it the same as I had for other ADDINs.

Thank you for your help!

[TransactionAttribute(TransactionMode.Manual)]
[RegenerationAttribute(RegenerationOption.Manual)]
public class CicuitChecker : IExternalCommand
{

    public Result Execute(
      ExternalCommandData commandData,
      ref string message,
      ElementSet elements)
    {
        //set document variable
        Document document = commandData.Application.ActiveUIDocument.Document;

        using (Transaction trans = new Transaction(document))
        {
            trans.Start("Circuit Checker");
            UIApplication uiApp = commandData.Application;
            Document doc = uiApp.ActiveUIDocument.Document;
            //run through looped form in case of user not selecting needed fields, and store what family the user wants the program to check
            Boolean messedUp = false;
            Boolean All = false, lightF = false, recep = false, elecEquip = false, equipCon = false, junc = false, panels = false;
            FilteredElementCollector collector = new FilteredElementCollector(doc), collector2 = new FilteredElementCollector(doc);
            while (messedUp)
            { 
                CircuitChecker.CircuitCheckerForm form = new CircuitChecker.CircuitCheckerForm();
                form.ShowDialog();
                //Get application and document objects


                foreach (String item in form.getSelectionElementsLB())
                {
                    if (item.Equals("All"))
                    {
                        All = true;
                        break;
                    }
                    else if (item.Equals("Lighting Fixtures"))
                    {
                        lightF = true;
                    }
                    else if (item.Equals("Recepticales"))
                    {
                        recep = true;
                    }
                    else if (item.Equals("Electrical Equipment (including Panels)"))
                    {
                        elecEquip = true;
                    }
                    else if (item.Equals("Junctions"))
                    {
                        junc = true;
                    }
                    else
                    {
                        messedUp = true;
                        TaskDialog.Show("Error", "At least one element must be selected.");

                    }
                }

                if (form.getSelectionPlaceLB().Equals("Entire Project"))
                {
                    collector
                        = new FilteredElementCollector(doc)
                        .WhereElementIsNotElementType();
                    collector2
                        = new FilteredElementCollector(doc)
                        .WhereElementIsNotElementType();
                }
                else if (form.getSelectionPlaceLB().Equals("Elements in Current View"))
                {
                    collector
                        = new FilteredElementCollector(doc, document.ActiveView.Id)
                        .WhereElementIsNotElementType();
                    collector2
                        = new FilteredElementCollector(doc, document.ActiveView.Id)
                        .WhereElementIsNotElementType();
                }
                else
                {
                    messedUp = true;
                    TaskDialog.Show("Error", "A place must be selected.");
                }
            }


            Color color = new Color(138, 43, 226); // RGB
            OverrideGraphicSettings ogs = new OverrideGraphicSettings();
            OverrideGraphicSettings ogsOriginal = new OverrideGraphicSettings();
            ogs.SetProjectionLineColor(color);
            int notCircuited = 0;
            //ElementId symbolId = family
            ElementCategoryFilter lightFilter = new ElementCategoryFilter(BuiltInCategory.OST_LightingFixtures);
            ElementCategoryFilter recepFilter = new ElementCategoryFilter(BuiltInCategory.OST_ElectricalFixtures);
            ElementCategoryFilter elecEquipFilter = new ElementCategoryFilter(BuiltInCategory.OST_ElectricalEquipment);
            //ElementClassFilter filter = new ElementClassFilter(typeof("Junction Boxes - Load"));
            //FamilyInstanceFilter juncFilter1 = new FamilyInstanceFilter(doc, );
            LogicalOrFilter first = new LogicalOrFilter(lightFilter, recepFilter);

            if (All)
            {


                collector.WherePasses(first);
                IList<Element> allArr = collector.ToElements();
                foreach (Element e in allArr)
                {
                    int cirNum = e.get_Parameter(BuiltInParameter.RBS_ELEC_CIRCUIT_NUMBER).AsInteger();
                    String panel = e.get_Parameter(BuiltInParameter.RBS_ELEC_CIRCUIT_PANEL_PARAM).AsString();
                    if (!(IsNumeric(cirNum)) || (panel.Equals("")) || (panel.Equals("<unnamed>")))
                    {
                        doc.ActiveView.SetElementOverrides(e.Id, ogs);
                        notCircuited++;
                    }
                    else
                    {
                        doc.ActiveView.SetElementOverrides(e.Id, ogsOriginal);
                    }
                }
                collector2.WherePasses(elecEquipFilter);
                IList<Element> elecEquipArr = collector.ToElements();
                foreach (Element e in elecEquipArr)
                {
                    String panel = e.get_Parameter(BuiltInParameter.RBS_ELEC_PANEL_SUPPLY_FROM_PARAM).AsString();
                    if ((panel.Equals("")))
                    {
                        doc.ActiveView.SetElementOverrides(e.Id, ogs);
                        notCircuited++;
                    }
                    else
                    {
                        doc.ActiveView.SetElementOverrides(e.Id, ogsOriginal);
                    }
                }
                TaskDialog.Show("Circuit Checker", notCircuited + " lighting fixtures are not circuited in this view.");
                trans.Commit();
            }

            if (!trans.HasEnded())
            {
                if (lightF)
                {
                    collector.WherePasses(lightFilter);
                    IList<Element> lightArr = collector.ToElements();
                    foreach (Element e in lightArr)
                    {
                        int cirNum = e.get_Parameter(BuiltInParameter.RBS_ELEC_CIRCUIT_NUMBER).AsInteger();
                        String panel = e.get_Parameter(BuiltInParameter.RBS_ELEC_CIRCUIT_PANEL_PARAM).AsString();
                        if (!(IsNumeric(cirNum)) || (panel.Equals("")) || (panel.Equals("<unnamed>")))
                        {
                            doc.ActiveView.SetElementOverrides(e.Id, ogs);
                            notCircuited++;
                        }
                        else
                        {
                            doc.ActiveView.SetElementOverrides(e.Id, ogsOriginal);
                        }
                    }
                }

                if (recep)
                {
                    collector.WherePasses(recepFilter);
                    IList<Element> recepArr = collector.ToElements();
                    foreach (Element e in recepArr)
                    {
                        int cirNum = e.get_Parameter(BuiltInParameter.RBS_ELEC_CIRCUIT_NUMBER).AsInteger();
                        String panel = e.get_Parameter(BuiltInParameter.RBS_ELEC_CIRCUIT_PANEL_PARAM).AsString();
                        if (!(IsNumeric(cirNum)) || (panel.Equals("")) || (panel.Equals("<unnamed>")))
                        {
                            doc.ActiveView.SetElementOverrides(e.Id, ogs);
                            notCircuited++;
                        }
                        else
                        {
                            doc.ActiveView.SetElementOverrides(e.Id, ogsOriginal);
                        }
                    }
                }
                if (elecEquip)
                {
                    collector.WherePasses(elecEquipFilter);
                    IList<Element> elecEquipArr = collector.ToElements();
                    foreach (Element e in elecEquipArr)
                    {
                        String panel = e.get_Parameter(BuiltInParameter.RBS_ELEC_PANEL_SUPPLY_FROM_PARAM).AsString();
                        if ((panel.Equals("")))
                        {
                            doc.ActiveView.SetElementOverrides(e.Id, ogs);
                            notCircuited++;
                        }
                        else
                        {
                            doc.ActiveView.SetElementOverrides(e.Id, ogsOriginal);
                        }
                    }
                }
                if (junc)
                {
                    collector.WherePasses(recepFilter);
                    IList<Element> juncArr = collector.ToElements();
                    foreach (Element e in juncArr)
                    {
                        int cirNum = e.get_Parameter(BuiltInParameter.RBS_ELEC_CIRCUIT_NUMBER).AsInteger();
                        String panel = e.get_Parameter(BuiltInParameter.RBS_ELEC_CIRCUIT_PANEL_PARAM).AsString();
                        if (!(IsNumeric(cirNum)) || (panel.Equals("")) || (panel.Equals("<unnamed>")))
                        {
                            doc.ActiveView.SetElementOverrides(e.Id, ogs);
                            notCircuited++;
                        }
                        else
                        {
                            doc.ActiveView.SetElementOverrides(e.Id, ogsOriginal);
                        }
                    }
                }

                TaskDialog.Show("Circuit Checker", notCircuited + " lighting fixtures are not circuited in this view.");
                trans.Commit();
            }
        }
        return Result.Succeeded;
    }
    public static Boolean IsNumeric(Object Expression)
    {
        if (Expression == null || Expression is DateTime)
            return false;

        if (Expression is Int16 || Expression is Int32 || Expression is Int64 || Expression is Decimal || Expression is Single || Expression is Double || Expression is Boolean)
            return true;

        try
        {
            if (Expression is string)
                Double.Parse(Expression as string);
            else
                Double.Parse(Expression.ToString());
            return true;
        }
        catch { } // just dismiss errors but return false
        return false;
    }
}

This code is having the functionality in the 'main class.' I have since moved the functionality to the form class as konrad suggested but am still receiving the FullClassName error in Revit. Please Help!

Jacob Bunzel
  • 165
  • 1
  • 4
  • 15
  • Next time please post relevant code in textual form. You can copy/paste it here and then use CTR+K to convert it to code formatting. – konrad Jul 01 '17 at 01:29

3 Answers3

0

Here's how I usually set up my Windows Forms based External Commands. Remember that you have to create an External Command, and your addin manifest must point at this class. Then from this class you can launch the Form like so:

    [Transaction(TransactionMode.Manual)]
    public class SomeCommand : IExternalCommand
    {
        public Result Execute(
            ExternalCommandData commandData,
            ref string message,
            ElementSet elements)
        {
            // Get application and document objects
            UIApplication uiApp = commandData.Application;
            Document doc = uiApp.ActiveUIDocument.Document;
            UIDocument uidoc = uiApp.ActiveUIDocument;

            try
            {
                SomeNamespace.SomeForm form = new SomeNamespace.SomeForm(doc);
                form.ShowDialog();

                return Result.Succeeded;
            }
            // Catch any exceptions and display them
            catch (Autodesk.Revit.Exceptions.OperationCanceledException)
            {
                return Result.Cancelled;
            }
            catch (Exception ex)
            {
                message = ex.Message;
                return Result.Failed;
            }
        }
    }

So I have a Form class that I instantiate from my ExternalCommand and pass Document to its constructor. That way I have access to document when I am interacting with the form later. I wire up all functionality in code behind of the Form.

konrad
  • 3,544
  • 4
  • 36
  • 75
  • Your answer is helpful but does not answer my problem. I know I need to point to the 'main class' but I still get an error. Should I follow exactly what you did and just have the actual processing part of the program run in the form class? I have put my main class in the question now: should I just replace that with what you have and put what's in my main class into my form class? I am still very confused as to why this isn't working and it is becoming frustrating. It must be some small stupid mistake, but I know it is still building. Please also look at my ADDIN file to check it. – Jacob Bunzel Jul 01 '17 at 14:06
  • I did as you suggested but I still get that same Revit error saying that the FullClassName is wrong. Please take a look at it and let me know if anything is wrong – Jacob Bunzel Jul 01 '17 at 15:01
  • That's an issue with the button method. When you create a new PushButtonData() you have to give it a ExternalCommand class name as one of the arguments. Make sure that's a full class name including the Namespace. So for the example above it would be "Namespace.SomeClass". If you don't have a button but instead are just using the addin method then your addin manifest needs to include a full name of the class prefixed with the namespace. – konrad Jul 01 '17 at 23:41
  • I changed the ADDIN file to be namespace.program and I put my 'main class' in the namespace but it did not help. I'm not entirely sure what you are telling me to do, or if I have already done it. – Jacob Bunzel Jul 02 '17 at 17:39
0

The schedule data add-in provides a full Visual Studio solution demonstrating how to display a Windows form in a Revit add-in, including the generation of the Windows form on the fly:

http://thebuildingcoder.typepad.com/blog/2012/05/the-schedule-api-and-access-to-schedule-data.html

Jeremy Tammik
  • 7,333
  • 2
  • 12
  • 17
  • I am trying to use the schedule data add-in as a guide but the autodesk.windows namespace does not work and I cannot find the reference needed for it. – Jacob Bunzel Jul 01 '17 at 13:51
  • Also, @JeremyTammik this does not answer my question. I believe I have my form set up correctly now with konrad's help, but the core of the problem is still the add-in file, more specifically the FullClassName. Please look at the screenshots of my error because this is becoming frustrating! – Jacob Bunzel Jul 01 '17 at 15:05
  • @JacobBunzel everything you need to know about the add-in manifest is explained in the [getting started material](http://thebuildingcoder.typepad.com/blog/about-the-author.html#2) and the [developers guide](http://help.autodesk.com/view/RVT/2018/ENU/?guid=GUID-F0A122E0-E556-4D0D-9D0F-7E72A9315A42). – Jeremy Tammik Jul 02 '17 at 21:21
  • You have a backslash in your class name instead of a dot. It has to be a full class name including its namespace. CircuitChecker.CircuitChecker.dll. No backslash, but a period instead. Jeremy is completely right. Please read the getting started material first. – konrad Jul 03 '17 at 03:40
  • The assembly is the path to the dll. So, since I have it in the CircuitCheckers folder, I go CircuitCheckers\CircuitChecker.dll And I have looked at the starting material before. I have made the ADDIN file based on that and it does not work. That is why I am asking for help. – Jacob Bunzel Jul 05 '17 at 12:45
  • Is the error message still exactly the same as before, in Q5? – Matt Jul 06 '17 at 18:56
  • whenever i have some add-in code that does not work, i simply create a completely new add-in using the [Visual Studio Revit Add-In Wizard](http://thebuildingcoder.typepad.com/blog/about-the-author.html#5.20) and copy the existing add-in code into the new skeleton modules. fool-proof, five clicks, works every time. [KISS](https://en.wikipedia.org/wiki/KISS_principle)! – Jeremy Tammik Jul 06 '17 at 20:29
  • I completely made a new program and I used the IWin32Window variable that Jeremy used in his; either that or just redoing the program helped! Thanks for the help (although I am still confused why my current program did work, oh well)! – Jacob Bunzel Jul 07 '17 at 13:55
  • yay! congratulations! – Jeremy Tammik Jul 07 '17 at 21:20
0

Agree, the OP's question is why doesn't the addin work... From looking at the images, it seems like the issue is that Revit is not properly finding the full class name of the command.

It's a little unusual that you don't have your command class wrapped in a namespace (your form class is, for example).

I would recommend wrapping it in a namespace like "circuitchecker" - like your form class.

Then the "full name" in the addin file would become "circuitchecker.circuitchecker"

(the namespace.classname) - this helps Revit distinguish different classes that might have the same name.

side note: I don't believe that putting a URL into the Image/LargeImage fields in the addin will work - but not positive.

Matt
  • 1,043
  • 5
  • 8
  • I tried this just now and it still did not work. I'm not sure what else to do. The actual program works fine but for some reason the FullClassName is stil the issue. Please help me look into it if you can – Jacob Bunzel Jul 02 '17 at 17:41
  • Show a screenshot or cut/paste of your command class (showing namespace) and your addin file – Matt Jul 02 '17 at 18:06
  • Here is a link to the screenshots, @Matt https://www.dropbox.com/sh/turp45fjg53k3m6/AADXbNdT6V1kHMuAyBI4IUZ3a?dl=0 – Jacob Bunzel Jul 05 '17 at 12:44