Revit API - Wrong full class name

2k views Asked by At

I'm very new to C# and coding. If possible I'm after some assistance figuring out how to fix this piece of code up to work.

They work individually. I can create a new button on the ribbon and execute the standard hello world. i also have a macro which works where I can remove all my sheets and views successfully but trying to combine the two is causing big difficulties! The code builds OK but I'm getting this error inside revit:

'Failed to initialize the add-in "Delete Views" because the class "DeleteViews" cannot be found in the add-in assembly.The FullClassName provides the enrty point for Revit to call add-in application. For Revit to run the add-in, you must ensure this class implements the "Autodesk.Revit.UI.ExternalCommand" interface.'

I'm pretty sure my problem is referencing in this 2nd bit of code. i know I'm not calling it up correctly but haven't been able to find any solutions.

Apologies if this is a dumb question but would really appreciate any help to help me learn!

Thanks for any help you can give me

The code:

namespace BGPanel
{
public class CsBGPanel : IExternalApplication
{
    public UIDocument ActiveUIDocument { get; private set; }
    public Result OnStartup(UIControlledApplication application)
    {
        RibbonPanel ribbonPanel = application.CreateRibbonPanel("Tools");

        string thisAssemblyPath = Assembly.GetExecutingAssembly().Location;
        PushButtonData buttonData = new PushButtonData("cmdDeleteViews",
           "Delete Views", thisAssemblyPath, "BGPanel.DeleteViews");

        PushButton pushButton = ribbonPanel.AddItem(buttonData) as PushButton;

        pushButton.ToolTip = "Delete all sheets, schedules & views except structural plans";

        Uri uriImage = new Uri(@"C:\Revit_API\Revit_2015\32px-Broom.png");
        BitmapImage largeImage = new BitmapImage(uriImage);
        pushButton.LargeImage = largeImage;

        return Result.Succeeded;
    }

         public void DeleteViews()
    {
        UIDocument uidoc = this.ActiveUIDocument;
        Document doc = uidoc.Document;

        FilteredElementCollector collector = new FilteredElementCollector(doc);
        ICollection<Element> collection = collector.OfClass(typeof(View)).ToElements();

        using (Transaction t = new Transaction(doc, "Delete Views"))
        {
            t.Start();

            int x = 0;

            foreach (Element e in collection)
            {
                try
                {
                    View view = e as View;

                    switch (view.ViewType)
                    {
                        case ViewType.FloorPlan:
                            break;
                        case ViewType.EngineeringPlan:
                            break;
                        case ViewType.ThreeD:
                            break;
                        default:
                            doc.Delete(e.Id);
                            x += 1;
                            break;
                    }
                }
                catch (Exception ex)
                {
                    View view = e as View;
                    TaskDialog.Show("Error", e.Name + "\n" + "\n" + ex.Message);
                    TaskDialog.Show("Error", ex.Message);
                }
            }
            t.Commit();

            TaskDialog.Show("BG_API DeleteViews", "Views Deleted: " + x.ToString());
        }

    }
    public Result OnShutdown(UIControlledApplication application)
    {
        return Result.Succeeded;
    }
}
}
6

There are 6 answers

0
Augusto Goncalves On

First, instead typing the class name yourself, consider using Reflection like:

typeof(YourClassName).FullName

Second, every command in Revit requires its own class that implements IExternalCommand. I haven't tested, but your code should be something like the following:

using System;
using System.Collections.Generic;
using System.Reflection;
using System.Windows.Media.Imaging;

using Autodesk.Revit.DB;
using Autodesk.Revit.UI;

namespace BGPanel
{
  public class CsBGPanel : IExternalApplication
  {
    public Result OnStartup(UIControlledApplication application)
    {
      RibbonPanel ribbonPanel = application.CreateRibbonPanel("Tools");

      string thisAssemblyPath = Assembly.GetExecutingAssembly().Location;
      PushButtonData buttonData = new PushButtonData("cmdDeleteViews",
         "Delete Views", thisAssemblyPath, typeof(DeleteViews).FullName);

      PushButton pushButton = ribbonPanel.AddItem(buttonData) as PushButton;

      pushButton.ToolTip = "Delete all sheets, schedules & views except structural plans";

      Uri uriImage = new Uri(@"C:\Revit_API\Revit_2015\32px-Broom.png");
      BitmapImage largeImage = new BitmapImage(uriImage);
      pushButton.LargeImage = largeImage;

      return Result.Succeeded;
    }

    public Result OnShutdown(UIControlledApplication application)
    {
      return Result.Succeeded;
    }
  }

  public class DeleteViews : IExternalCommand
  {
    // this will not work...
    //public UIDocument ActiveUIDocument { get; private set; }

    public Result Execute(ExternalCommandData commandData, ref string message, ElementSet elements)
    {
      UIDocument uidoc = commandData.Application.ActiveUIDocument; //this.ActiveUIDocument;
      Document doc = uidoc.Document;

      FilteredElementCollector collector = new FilteredElementCollector(doc);
      ICollection<Element> collection = collector.OfClass(typeof(View)).ToElements();

      using (Transaction t = new Transaction(doc, "Delete Views"))
      {
        t.Start();

        int x = 0;

        foreach (Element e in collection)
        {
          try
          {
            View view = e as View;

            switch (view.ViewType)
            {
              case ViewType.FloorPlan:
                break;
              case ViewType.EngineeringPlan:
                break;
              case ViewType.ThreeD:
                break;
              default:
                doc.Delete(e.Id);
                x += 1;
                break;
            }
          }
          catch (Exception ex)
          {
            View view = e as View;
            TaskDialog.Show("Error", e.Name + "\n" + "\n" + ex.Message);
            TaskDialog.Show("Error", ex.Message);
          }
        }
        t.Commit();

        TaskDialog.Show("BG_API DeleteViews", "Views Deleted: " + x.ToString());
      }
      return Result.Succeeded; // must return here
    }
  }
}
0
Jeremy Tammik On

You should work through the Revit API getting started material before doing anything else at all, especially the DevTV and My First Revit Plugin video tutorials:

http://thebuildingcoder.typepad.com/blog/about-the-author.html#2

Then this question and many other fundamental issues will be answered up front, and you will save yourself and others some effort and head-scratching.

0
Rory On

I needed to add a line before the IExternalCommand because of transaction errors when I clicked my button.

[Transaction(TransactionMode.Manual)]
4
Brandon On

The first answer to this question suggests using the reflection "typeof(YourClassName).FullName" When the sample code is tried it returns a error, understandably as Augusto says he did not test his example. Just adding for anyone down the road... If you use "typeof(DeleteViews).FullName" you would need to cast it into a string variable before the code in his example would work.

0
KungPhoo On

I had the function, that creates the button in the ribbon bar in a 2nd helper DLL, so the string thisAssemblyPath = Assembly.GetExecutingAssembly().Location; had to be changed to string thisAssemblyPath = Assembly.GetCallingAssembly().Location;. Make sure, you provide the correct path to the DLL, where you class derived from IExternalCommand is in.

0
AAGFX On

I know it is so old article but I prefere to add an answer for whom will get the same probleme..

En addition of what others said, verfiy the name of public class CsBGPanel : IExternalApplication

It must be as the name of class

It happend to me!