Sei sulla pagina 1di 9

6/20/2020 building revit plug-ins with visual studio: part three | archi-lab

Home
About me
Services
Examples
Portfolio
Reading
Membership

building revit plug-ins with visual studio: part three


By Konrad K Sobon / 23 Nov 2015 / 6 Comments
image by archi-lab

In this post I will go over a few things:

Implementing ISelectionFilter
which we will use while prompting user to select things via UI

Before we even get to selection stuff let’s first make sure that we have our application and documents needed. We specified that to be the
first thing to do in our pseudo code so let’s do that first:

1 UIApplication uiApp = commandData.Application;

uiApp.cs hosted with ❤ by GitHub view raw

Now I will go over it line by line:

1. uiApp is our Revit application. This will give us project level access to Revit database.

Next we want to prompt a user to select bunch of lines, so that we can measure their length. While user is selecting them we want to filter
out any objects that are not Detail Lines. For that we can use something called ISelectionFilter like so:

1 public class DetailLineFilter : ISelectionFilter

https://archi-lab.net/building-revit-plug-ins-with-visual-studio-part-three/ 1/9
6/20/2020 building revit plug-ins with visual studio: part three | archi-lab
2 {
3 public bool AllowElement(Element e)
4 {
5 return (e.Category.Id.IntegerValue.Equals(
6 (int)BuiltInCategory.OST_Lines));
7 }
8 public bool AllowReference(Reference r, XYZ p)
9 {
10 return false;
11 }
12 }

selectionFilter.cs hosted with ❤ by GitHub view raw

Here’s the line by line breakdown:

1. create a new public class that implements ISelectionFilter


2. .
3. define first method that will return a boolean true for elements that we want to allow.
4. .
5. define return statement. our rule is that if selected element Category Id value equals to that of BuiltInCategory.OST_Lines elements
will be passed through. Basically we only allow Lines to pass through.
6. .
7. .
8. define second method for allowing references.
9. .
10. since we don’t want to pass references through we simply return false here.
11. .
12. .

What this method will do, is that it will allow us to select only elements that are of category OST_Lines. That’s a pretty nifty little tool
that is super helpful in our case.

Let’s implement this filter in our code, and prompt a user to select something:

1 IList<Element> pickedRef = null;


2 Selection sel = uiApp.ActiveUIDocument.Selection;
3 DetailLineFilter selFilter = new DetailLineFilter();
4 pickedRef = sel.PickElementsByRectangle(selFilter, "Select lines");

implementSelectionFilter.cs hosted with ❤ by GitHub view raw

Here’s a line by line breakdown:

1. create a new empty list of Elements that will be populated with elements selected by user.
2. this is just a shortcut so that I don’t have to type out a super long line of code later.
3. This defines our Selection class that will be used to prompt user to select things.
4. Now that we have our filter class defined let’s create an instance of it and assign it to “selFilter” variable.
5. This prompts user to “select lines” and when user is done will populate pickedRef list with selected elements.

This is what our code should look like to this point*:

*You should also notice that I added another using statement at line 10. This is just to make our code cleaner at line 42. If I didn’t add a
using statement pointing directly at Selection class I would have to change line 42 to something like this:

Selection.Selection sel = uiApp.ActiveUIDocument.Selection;

That’s arguably much muddier hence the using statement. :-)

Let’s Build this project now, and replace the dll file in Revit Addins folder. You don’t have to worry about the addin file, since that hasn’t
changed. This is what we should be getting now in Revit:

https://archi-lab.net/building-revit-plug-ins-with-visual-studio-part-three/ 2/9
6/20/2020 building revit plug-ins with visual studio: part three | archi-lab

1. This is area of my rectangle used to select things.


2. Only Detail Lines present within the selection rectangle were highlighted (selected). This means that our selection filter is working
just fine. :-)

Now that we have out selection filter implemented we can move on to rest of our code that will measure the length of all of the selected
lines and return a value for you. First I want to iterate through my list of selected curves and return their length:

1 List<double> lengthList = new List<double>();


2 foreach (Element e in pickedRef)
3 {
4 DetailLine line = e as DetailLine;
5 if (line != null)
6 {
7 lengthList.Add(line.GeometryCurve.Length);
8 }
9 }

listIteration.cs hosted with ❤ by GitHub view raw

Here’s the line by line breakdown.

1. each length is a double (a number) so we need a new list to store them in.
2. this starts a new foreach loop that will iterate through every selected detail line
3. .
4. since when lines were selected they were returned to us as Element objects we need to cast them to DetailLine class. We do that
because we want to be able to access DetailLine properties of each of the Elements.
5. if somehow our cast failed it will return null. let’s check that we are not getting a null value here
6. .
7. now let’s add the Length of the line to our list
8. .
9. ..

Now we should have a list that holds bunch of number values. Each value represents a length of the detail line. All we have to do now, is
sum them all up and return that information to the user. Also, I mentioned before that I am interested in returning that info not only in
imperial units of length but also in metric. This will require a few extra lines of code but it’s easy enough to cover here:

1 string lengthFeet = Math.Round(lengthList.Sum(), 2).ToString() + " ft";


2 string lengthMeters = Math.Round(lengthList.Sum() * 0.3048, 2).ToString() + " m";
3 string lengthMilimeters = Math.Round(lengthList.Sum() * 304.8, 2).ToString() + " mm";
4 string lengthInch = Math.Round(lengthList.Sum() * 12, 2).ToString() + " inch";
5
6 StringBuilder sb = new StringBuilder();
7 sb.AppendLine("Total Length is:");
8 sb.AppendLine(lengthFeet);

https://archi-lab.net/building-revit-plug-ins-with-visual-studio-part-three/ 3/9
6/20/2020 building revit plug-ins with visual studio: part three | archi-lab
9 sb.AppendLine(lengthInch);
10 sb.AppendLine(lengthMeters);
11 sb.AppendLine(lengthMilimeters);
12
13 TaskDialog.Show("Line Length", sb.ToString());

returnValues.cs hosted with ❤ by GitHub view raw

Here’s the line by line breakdown:

1. here we build a string that will read out total length in ft. I also add a Math.Round method to round our results to two decimal places.
2. here we build a string that will read out total length in meters. Since all values returned by Revit are always in ft we have to add a *
0.3048 to convert from ft to m.
3. same as above but this time we convert to mm.
4. same as above but this time we convert to inch by multiplying by 12.
5. .
6. we create a new instance of String Builder. String Builder is an object that can be used to quickly concatenate bunch of strings into
one continues string.
7. first we append “Total Length is: ” to string builder.
8. then we append a new line that has our total length in ft.
9. then we append a new line that has our total length in inches.
10. then we append a new line that has our total length in meters
11. finally we append a new line that has our total length in mm
12. .
13. last step of our code is to show the results to user. We can use a very simple TaskDialog object to do that. It will show a simple
message window to the user that will contain our StringBuilder object converted to string.

This should be it. Here’s all of our code for this example:

1 using System;
2 using System.Collections.Generic;
3 using System.Linq;
4 using System.Text;
5 using System.Threading.Tasks;
6
7 using Autodesk.Revit.DB;
8 using Autodesk.Revit.UI;
9 using Autodesk.Revit.Attributes;
10 using Autodesk.Revit.UI.Selection;
11
12 namespace TotalLength
13 {
14 [Transaction(TransactionMode.Manual)]
15 public class CurveTotalLength : IExternalCommand
16 {
17 public class DetailLineFilter : ISelectionFilter
18 {
19 public bool AllowElement(Element e)
20 {
21 return (e.Category.Id.IntegerValue.Equals(
22 (int)BuiltInCategory.OST_Lines));
23 }
24 public bool AllowReference(Reference r, XYZ p)
25 {
26 return false;
27 }
28 }
29
30 public Result Execute(
31 ExternalCommandData commandData,
32 ref string message,
33 ElementSet elements)
34 {
35 // Get application and document objects
36 UIApplication uiApp = commandData.Application;

https://archi-lab.net/building-revit-plug-ins-with-visual-studio-part-three/ 4/9
6/20/2020 building revit plug-ins with visual studio: part three | archi-lab

37
38 try
39 {
40 // Implement Selection Filter to select curves
41 IList<Element> pickedRef = null;
42 Selection sel = uiApp.ActiveUIDocument.Selection;
43 DetailLineFilter selFilter = new DetailLineFilter();
44 pickedRef = sel.PickElementsByRectangle(selFilter, "Select lines");
45
46 // Measure their total length
47 List<double> lengthList = new List<double>();
48 foreach (Element e in pickedRef)
49 {
50 DetailLine line = e as DetailLine;
51 if (line != null)
52 {
53 lengthList.Add(line.GeometryCurve.Length);
54 }
55 }
56
57 string lengthFeet = Math.Round(lengthList.Sum(), 2).ToString() + " ft";
58 string lengthMeters = Math.Round(lengthList.Sum() * 0.3048, 2).ToString() + " m";
59 string lengthMilimeters = Math.Round(lengthList.Sum() * 304.8, 2).ToString() + " mm";
60 string lengthInch = Math.Round(lengthList.Sum() * 12, 2).ToString() + " inch";
61
62 StringBuilder sb = new StringBuilder();
63 sb.AppendLine("Total Length is:");
64 sb.AppendLine(lengthFeet);
65 sb.AppendLine(lengthInch);
66 sb.AppendLine(lengthMeters);
67 sb.AppendLine(lengthMilimeters);
68
69 // Return a message window that displays total length to user
70 TaskDialog.Show("Line Length", sb.ToString());
71
72 // Assuming that everything went right return Result.Succeeded
73 return Result.Succeeded;
74 }
75 // This is where we "catch" potential errors and define how to deal with them
76 catch (Autodesk.Revit.Exceptions.OperationCanceledException)
77 {
78 // If user decided to cancel the operation return Result.Canceled
79 return Result.Cancelled;
80 }
81 catch (Exception ex)
82 {
83 // If something went wrong return Result.Failed
84 message = ex.Message;
85 return Result.Failed;
86 }
87 }
88 }
89 }

curveTotalLength.cs hosted with ❤ by GitHub view raw

Now if we Build this and again replace the DLL file with the latest one, this should be our result in Revit:

https://archi-lab.net/building-revit-plug-ins-with-visual-studio-part-three/ 5/9
6/20/2020 building revit plug-ins with visual studio: part three | archi-lab

This is it! If you stuck around with me, for this long, you were just able to build your first Revit plug-in. I am thinking about extending this
into a series, and next time going over taking our External Command addin and showing you guys how to add it to a larger set of tools. I
would like to show you how to create your own tab on Revit ribbon, add buttons and proper icons for your own tool-set branding. Since I
already shared a small tool, called Legend Duplicator few weeks ago, it will be easy to take these two and put them together under our own
tab in Revit.

Final DLL and Addin files can be downloaded from here:

CurveTotalLength (478 downloads)

Thanks for following!

Support archi-lab on Patreon!

Share this:

 Twitter  Facebook  LinkedIn  Pinterest  Print

Posted in: C#, Revit / Tagged: C++, IExternalCommand, ISelectionFilter, revit, revit api, revit plug-ins

6 Comments

1.
Jason says:
January 9, 2017 at 10:34 pm · Reply

Just finished the first three lessons on this, and after a little stumbling around, got my line length totals working! Thanks for taking
the time to put this together.
(Only real struggle was where we’d jump to a new section of code, trying to figure out where to pick up, but I think that’s with my
lack of knowledge of C# structures. The ‘complete’ code at the bottom was my road map.)

Konrad K Sobon says:


January 12, 2017 at 5:29 pm · Reply

Glad you got it to work. Cheers!

2.
Jorge Villarroel says:
November 10, 2017 at 1:34 pm · Reply

Hi Konrad,

https://archi-lab.net/building-revit-plug-ins-with-visual-studio-part-three/ 6/9
6/20/2020 building revit plug-ins with visual studio: part three | archi-lab
Really nice work with this. For me, it was really helpful to start with the C# coding. Also, I got some things that I’ll surely use in my
future apps.

Have some questions:

– The process mentioned here is that after you build the app, you just copy the updated .dll file to the folder. I would like to know
how to properly set the Visual Studio to re-write the updated .dll file at the %appdata% folder.

– Following the previous question, I also wanted to configure my Visual Studio to debug the code using Revit, so I tried to do the
explained procedure here: https://www.youtube.com/watch?v=C0mNU2bEUSs&index=19&list=WL .

– Finally, I looked the setting from the Jeremy Tammik’s template.

When I press “Start” button in VS, I get an execution error in REVIT and have to stop the process.

As a summary, I want to know how to code in VS and test the codes I write but not having to Open-Close Revit in every iteration.

Thanks in advance for your help!

Attachment: ExecutionError.png

Konrad K Sobon says:


November 27, 2017 at 4:35 am · Reply

You can try this in the post build event: xcopy /Q/Y “$(TargetDir)some.dll”
“%ALLUSERSPROFILE%\Autodesk\Revit\Addins\2018”. For debugging on top of revit make sure you have the Start
external program setting in Debug tab set to appropriate version of Revit.exe file. Then you also have to change the Use native
compatibility mode to be unchecked under the Tools>Options>Debugging. Finally you can use the External Addin Manager to
re-load the DLL in question and test your plug-in without having to restart revit. For that to work though you don’t place the
dlls in the addins folder, so all previous pointers are useless.

3.
Maikel says:
February 13, 2018 at 8:34 am · Reply

Hi Konrad,

Very thanks for this lessons. It helps me a lot forward to achieve my goal.
When I write this for a detail line it works perfect.

But when I try this to do for ducts, I am very struggling.


Do you know how I can get this done for the “Length” and “Area” parameter for a collection of ducts?

Thanks in advance for your help!

Trackbacks
1. Weekly Roundup – 2015.49 | The BIMsider

Leave a Comment

Name *

Email *

Website

Save my name, email, and website in this browser for the next time I comment.

Upload Attachment (Allowed file types: jpg, gif, png, pdf, doc, docx, ppt, pptx, pps, ppsx, odt, xls, xlsx, rar, zip, mp3, m4a, ogg, wav, wma, mp4, m4v, mov,
wmv, avi, mpg, ogv, 3gp, 3g2, flv, webm, apk, maximum file size: 2MB.

https://archi-lab.net/building-revit-plug-ins-with-visual-studio-part-three/ 7/9
6/20/2020 building revit plug-ins with visual studio: part three | archi-lab
Choose File No file chosen

Notify me of follow-up comments by email.

Notify me of new posts by email.

Submit Comment

Search

To search type and hit enter

Categories
Select Category

Recent Posts

Comparing View Templates in Dynamo June 18, 2020


how to maintain Revit plugins for multiple versions continued… May 25, 2020
create ceiling plan by room April 19, 2020
In depth look at Dynamo and Revit relationship w/ Bimbeats March 28, 2020
creating curtain wall plans/elevations pt2 March 18, 2020

Calendar
June 2020
M T W T F S S
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30
« May

Tags

AEC archi-lab architecture autodesk automation BIM C++ coding community computation computational computational BIM
computational design curtain wall d3 data delete design development documentation dynamo excel grasshopper hackathon html
mandrill mantis shrimp open source parsing programming python revit revit api revit plug-in rhino schedules scripting symposium tags

technology view template visualization visual programming visual studio warnings


← building revit plug-ins with visual studio: part two
create your own tab and buttons in revit →

archi-lab tweets:
RT @archikaos: @arch_laboratory Absolutely a win! It's such a pleasure working with @arch_laboratory and honor to contribute to
open source19 Jun 2020
Comparing View Templates inDynamo https://t.co/sxWkyu4zmV18 Jun 2020
RT @Gytaco: Pretty cool when some of the tech you've been working on makes the local news. Been great to build the backend
platform to inte12 Jun 2020
RT @MGortat: https://t.co/jdYIUo2rjU polecam ! Cala prawda o czowieku zarzdzajcym Polska koszykwka. 03 Jun 2020
@gtalarico Yours is one of a kind...sorry, but no documentation for one offs. Next time try and order at least two. Congrats! 31 May
2020
@60secondrevit @DynamoBIM Yeah, I agree. Its useless and quite heidious too.27 May 2020

Project Gallery

https://archi-lab.net/building-revit-plug-ins-with-visual-studio-part-three/ 8/9
6/20/2020 building revit plug-ins with visual studio: part three | archi-lab

Membership:

Search:

To search type and hit enter

Categories:

Select Category

Tags:

AEC archi-lab architecture autodesk automation BIM C++ coding community computation computational computational BIM
computational design curtain wall d3 data delete design development documentation dynamo excel grasshopper hackathon html
mandrill mantis shrimp open source parsing programming python revit revit api revit plug-in rhino schedules scripting symposium tags

technology view template visualization visual programming visual studio warnings

© Copyright 2020. Powered by WordPress

Viewport Theme by ThemeZilla

https://archi-lab.net/building-revit-plug-ins-with-visual-studio-part-three/ 9/9

Potrebbero piacerti anche