Is there a built in category or class that would allow me to create an ISelectionFilter that selects views that are not legends?
Solved! Go to Solution.
Solved by n_mulconray. Go to Solution.
Solved by FAIR59. Go to Solution.
Solved by RPTHOMAS108. Go to Solution.
I'm not aware of a builtin solution but this should do the trick:
ParameterValueProvider pvp_ParamElem = new ParameterValueProvider(new ElementId((int) BuiltInParameter.VIEW_FAMILY)); FilterStringEquals fequals = new FilterStringEquals(); FilterStringRule LegendRule = new FilterStringRule(pvp_ParamElem,fequals,"Legends",false); ElementParameterFilter efilter = new ElementParameterFilter(LegendRule,true); FilteredElementCollector ViewsNonLegend = new FilteredElementCollector(doc) .OfClass(typeof (View)) .WherePasses(efilter);
NB: this will find Keynote Legends.[ Keynote Legends are "Schedules"]
I wanted to answer the ISelectionFilter question because I like this interface, however I don't believe it is appropriate for selecting views.
My alternative solution would be to expand each element via LINQ and read the ViewType property as below. Probably would be similar in performance to a combination of quick and slow filter. The below is more generic for getting views of various types. For the C# version I converted from VB and filled in the gaps of the LINQ expression (therefore C# version may have issues unknown to me).
e.g. I think the 'v == null == false' could have come out better (!=).
VB version
Public Shared Function AllViewsOfType(Doc As Document, VT As ViewType, Optional ReturnViewElementTypes As Boolean = False, _ Optional ReturnViewTemplates As Boolean = False) As List(Of ElementId) Dim ECF As New ElementClassFilter(GetType(View)) Dim FEC As New FilteredElementCollector(Doc) Dim V_EIDs As List(Of ElementId) = Nothing If ReturnViewElementTypes = True Then V_EIDs = FEC.WherePasses(ECF).WhereElementIsElementType.ToElementIds Else V_EIDs = FEC.WherePasses(ECF).WhereElementIsNotElementType.ToElementIds End If Dim Ien As IEnumerable(Of ElementId) Ien = From EID As ElementId In V_EIDs Let V As View = TryCast(Doc.GetElement(EID), View) Where V Is Nothing = False Where V.ViewType = VT AndAlso V.IsTemplate = ReturnViewTemplates Select EID Return Ien.ToList End Function Public Shared Function ExampleUse(Doc As Document) As List(Of ElementId) Return AllViewsOfType(Doc, ViewType.Legend) End Function
C# version.
public static List<ElementId> AllViewsOfType(Document Doc, ViewType VT, bool ReturnViewElementTypes = false, bool ReturnViewTemplates = false) { ElementClassFilter ECF = new ElementClassFilter(typeof(View)); FilteredElementCollector FEC = new FilteredElementCollector(Doc); List<ElementId> V_EIDs = null; if (ReturnViewElementTypes == true) { V_EIDs = FEC.WherePasses(ECF).WhereElementIsElementType.ToElementIds; } else { V_EIDs = FEC.WherePasses(ECF).WhereElementIsNotElementType.ToElementIds; } IEnumerable<ElementId> Ien = default(IEnumerable<ElementId>); Ien = from EID in V_EIDs let V = Doc.GetElement(EID) as View where V == null == false where V.ViewType == VT && V.IsTemplate == ReturnViewTemplates select EID; return Ien.ToList; } public static List<ElementId> ExampleUse(Document Doc) { return AllViewsOfType(Doc, ViewType.Legend); }
Thanx for the fast replies. I appreciate the options as well. However I was looking for something that is probably not achievable, A direct method to filter implementing the iselection interface. I was hoping to at least prevent users from selecting legends in
one of my c# Revit add-in tools.
public class LegendSelectionFilter : ISelectionFilter { public bool AllowElement(Element element) {
//Remove legends via a filter here if (element.Category.Name == "Enter a Category here") { return true; } return false; } public bool AllowReference(Reference refer, XYZ point) { return false; } }
I'm not sure you can select a view via Selection.PickObject/PickObjects (which the ISelectionFilter interface would be used for). However I've never tried since it never occured to me, how are the unfiltered views currently being selected?
If it were possible then the implementation would be fairly simple since you would just need to try casting the element provided by the AllowElement function to a View (if it is nothing return false). Otherwise check the View.ViewType property and return false if it is a Legend (to filter out legends) otherwise return true.
I presume the user will select a view (== a ViewPort instead of a View) on a sheet.
public class NonLegendViewFilter : ISelectionFilter { static ElementParameterFilter efilter; static NonLegendViewFilter() { ParameterValueProvider pvp_ParamElem = new ParameterValueProvider(new ElementId((int) BuiltInParameter.VIEW_FAMILY)); FilterStringEquals fequals = new FilterStringEquals(); FilterStringRule LegendRule = new FilterStringRule(pvp_ParamElem,fequals,"Legends",false); efilter = new ElementParameterFilter(LegendRule,true); } /// <summary> /// Do not allow LegendViewPorts to be selected /// </summary> /// <param name="elem">A candidate element in selection operation.</param> /// <returns>Return false for LegendViewPort, return false for non ViewPorts. </returns> public bool AllowElement(Element elem) { Viewport vp = elem as Viewport; if (vp==null) return false; return efilter.PassesFilter(elem.Document,vp.ViewId); } /// <summary> /// Allow reference to be selected /// </summary> /// <param name="refer">A candidate reference in selection operation.</param> /// <param name="point">The 3D position of the mouse on the candidate reference.</param> /// <returns>Return true for face reference. Return false for non face reference.</returns> public bool AllowReference(Reference refer, XYZ point) { return false; }
Can't find what you're looking for? Ask the community or share your knowledge.