应用程序:ViewFilters

Revit平台:所有

Revit版本:2011.0

首次推出:2011.0

编程语言:C#

技能等级:中级

类别:元素

类型:ExternalCommand

主题:创建和修改视图过滤器。

摘要:

本示例演示了如何使用2011年新元素迭代API创建和修改视图过滤器。

相关类:

Autodesk.Revit.UI.IExternalCommand

Autodesk.Revit.DB.FilteredElementCollector

Autodesk.Revit.DB.ParameterFilterElement

Autodesk.Revit.DB.ParameterFilterUtilities

Autodesk.Revit.DB.ParameterFilterRuleFactory

项目文件:

Command.cs

该文件包含从IExternalCommand接口继承并实现Execute方法的Command类。

ViewFiltersForm.cs

该文件包含一个Form类,该类由多个控件组成,以显示现有过滤器及其类别、过滤器规则;某些控件提供的功能允许修改过滤器和规则。

FilterData.cs

该文件定义了两个自定义数据类FilterDataFilterRuleData,表示API FilterFilterRule元素的数据;这两个数据缓存将有助于在UI控件上显示FilterFilterRules的内容。该文件还有一个RuleCriteraNames类,用于获取过滤器规则的字符串标准。

FiltersUtil.cs

该文件定义了FiltersUtil类,其中包括用于处理过滤器及其规则的一些实用方法。例如,从文档中获取现有过滤器;从FilterRule的评估器中获取标准(以字符串形式)。

Extension.cs

该文件具有处理EnumList相关的扩展实用程序类,用于解析枚举值和比较列表内容等。

描述:

该示例使用元素迭代API,尤其是ParameterFilterElement相关方法,来模拟UI命令:View \ Filters的功能。该示例还允许添加> 3的过滤器规则,并提供有关规则值的更多选项。

- 要查找文档中的所有视图过滤器,请使用ElementClassFiltertypeofParameterFilterElement))。

- ParameterFilterElement.Create...)方法可创建新的视图过滤器;其相关方法可访问或修改过滤器的类别/规则。

- ParameterFilterUtilities.GetAllFilterableCategories()方法可找到支持过滤的所有类别。

- ParameterFilterRuleFactory.CreateXXX()方法可相应地创建过滤器规则。

- 使用FilterInverseRule创建反转的过滤器规则,该规则反转其包含的规则返回的布尔值。

- Document.get_TypeOfStorageBuiltInParameter)可以获取参数的存储类型(int / double / string / elementid)。

- 视图过滤器(ParameterFilterElement)可以通过Document.Delete()方法删除。

- 通过反射基本FilterRule到其派生,我们可以找到此规则的详细信息:规则标准(equals / greater / less…),规则值。

说明:

1.通过UI命令创建一些过滤器,并指定过滤器规则:View选项卡à Graphics面板à Filters。在样本项目文件夹下提供一个ViewFilters.rvt文件,该项目具有一个具有四个过滤器规则的过滤器,该项目内的一些墙壁以不同的模式显示(通过View选项卡à Graphics面板à Graphics / Visibilityà Filters选项卡设置),因为这些墙壁通过过滤器和所有规则。

2.运行此示例:可以检索到所有现有过滤器及其过滤器规则;过滤器规则数据(参数、标准和规则值)将显示在相应的控件上。

3.UI命令相比,此示例提供了双精度值和区分大小写选项,允许用户为双精度/字符串参数指定它们;示例还允许显示和添加超过3个的过滤器。

4.对于过滤器:单击“New”按钮添加一个新过滤器;单击“delete”按钮删除某些过滤器。

5.通过更改所选类别以修改过滤器的类别,这也会重置过滤器规则。

6.对于过滤器规则:示例允许用户更改参数/标准/规则值以修改过滤器规则:要创建新的过滤器规则,请选择新参数并单击“New”按钮;在为现有规则修改标准/规则值之后,单击“Update”以应用更改;“Delete”按钮可以删除当前选定的规则。请注意,规则操作对Revit视图过滤器没有影响,直到您单击“OK”按钮,按以下项目进行应用更改。

7.单击“OK”按钮后,过滤器上的更改将生效并应用于Revit视图过滤器;您可以在UI视图过滤器中验证更改或在视图Visibility / Graphics设置中应用过滤器。

 8.注意:如果要将过滤器应用于特定视图,请通过Revit UI命令执行此操作:View选项卡-à Graphics面板-à Graphics / Visibilityà Filters选项卡,此示例尚不支持此功能,因为API尚未支持此功能。

注:

- Revit UI命令(View \ Filters)将规则数量限制为3个;通过API创建的> 3的规则将在您通过UI命令更新过滤器或规则时被删除。

-当创建过滤器规则时,此示例仅支持BuiltInParameter

-此示例仅适用于项目文档。

源代码:
完整的源代码请加入QQ群649037449,在群文件中下载RevitSDK.exe,解压后在文件夹中搜索本文中应用程序名称即可获得完整源码

Extensions.cs

//
// (C) Copyright 2003-2019 by Autodesk, Inc.
//
// Permission to use, copy, modify, and distribute this software in
// object code form for any purpose and without fee is hereby granted,
// provided that the above copyright notice appears in all copies and
// that both that copyright notice and the limited warranty and
// restricted rights notice below appear in all supporting
// documentation.
//
// AUTODESK PROVIDES THIS PROGRAM "AS IS" AND WITH ALL FAULTS.
// AUTODESK SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTY OF
// MERCHANTABILITY OR FITNESS FOR A PARTICULAR USE. AUTODESK, INC.
// DOES NOT WARRANT THAT THE OPERATION OF THE PROGRAM WILL BE
// UNINTERRUPTED OR ERROR FREE.
//
// Use, duplication, or disclosure by the U.S. Government is subject to
// restrictions set forth in FAR 52.227-19 (Commercial Computer
// Software - Restricted Rights) and DFAR 252.227-7013(c)(1)(ii)
// (Rights in Technical Data and Computer Software), as applicable.
//
using System;
using System.Text;
using System.Windows.Forms;
using System.Collections;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Diagnostics;
namespace Revit.SDK.Samples.ViewFilters.CS
{
    /// <summary>
    /// Generic utility class used to extend enum parse related methods
    /// </summary>
    /// <typeparam name="TEnum">Enum type for this class.</typeparam>
    public static class EnumParseUtility<TEnum>
    {
        /// <summary>
        /// Parse string to TEnum values
        /// </summary>
        /// <param name="strValue">Enum value in string.</param>
        /// <returns>TEnum value is parsed from input string.</returns>
        public static TEnum Parse(string strValue)
        {
            if (!typeof(TEnum).IsEnum) return default(TEnum);
            return (TEnum)Enum.Parse(typeof(TEnum), strValue);
        }
        /// <summary>
        /// Parse TEnum to string 
        /// </summary>
        /// <param name="enumVal">TEnum value to be parsed.</param>
        /// <returns>String parsed from input TEnum.</returns>
        public static String Parse(TEnum enumVal)
        {
            if (!typeof(TEnum).IsEnum) return String.Empty;
            return Enum.GetName(typeof(TEnum), enumVal);
        }
        /// <summary>
        /// Parse TEnum from integer value to string
        /// </summary>
        /// <param name="enumValInt">Integer value to be parsed.</param>
        /// <returns>String parsed from input TEnum(integer type)</returns>
        public static String Parse(int enumValInt)
        {
            if (!typeof(TEnum).IsEnum) return String.Empty;
            return Enum.GetName(typeof(TEnum), enumValInt);
        }
    }
    /// <summary>
    /// Generic utility class used to deal with List compare related methods.
    /// </summary>
    /// <typeparam name="T">Object type in list.</typeparam>
    public static class ListCompareUtility<T>
    {
        /// <summary>
        /// Check to see if two lists are equals
        /// When comparing, two list will be checked on amounts and contents
        /// </summary>
        /// <param name="coll1">1st list.</param>
        /// <param name="coll2">2nd list.</param>
        /// <returns>True if two list are identical on data.</returns>
        public static bool Equals(ICollection<T> coll1, ICollection<T> coll2)
        {
            if (coll1.Count != coll2.Count) return false;
            foreach (T val1 in coll1)
            {
                if (!coll2.Contains(val1)) return false;
            }
            foreach (T val2 in coll2)
            {
                if (!coll1.Contains(val2)) return false;
            }
            return true;
        }
    }
}

FilterData.cs

//
// (C) Copyright 2003-2019 by Autodesk, Inc.
//
// Permission to use, copy, modify, and distribute this software in
// object code form for any purpose and without fee is hereby granted,
// provided that the above copyright notice appears in all copies and
// that both that copyright notice and the limited warranty and
// restricted rights notice below appear in all supporting
// documentation.
//
// AUTODESK PROVIDES THIS PROGRAM "AS IS" AND WITH ALL FAULTS.
// AUTODESK SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTY OF
// MERCHANTABILITY OR FITNESS FOR A PARTICULAR USE. AUTODESK, INC.
// DOES NOT WARRANT THAT THE OPERATION OF THE PROGRAM WILL BE
// UNINTERRUPTED OR ERROR FREE.
//
// Use, duplication, or disclosure by the U.S. Government is subject to
// restrictions set forth in FAR 52.227-19 (Commercial Computer
// Software - Restricted Rights) and DFAR 252.227-7013(c)(1)(ii)
// (Rights in Technical Data and Computer Software), as applicable.
//

using System;
using System.Text;
using System.Windows.Forms;
using System.Collections;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Diagnostics;

using Autodesk.Revit;
using Autodesk.Revit.DB;
using Autodesk.Revit.UI;
using Autodesk.Revit.DB.Architecture;
using PFRF = Autodesk.Revit.DB.ParameterFilterRuleFactory;

namespace Revit.SDK.Samples.ViewFilters.CS
{
/// <summary>
/// Sample custom immutable class used to represents Revit internal FilterRule.
/// This class and its variables will help display the contents of UI controls.
/// This class can build its data caches to Revit FilterRule object.
/// </summary>
public sealed class FilterRuleBuilder
{
#region Class Member Variables
/// <summary>
/// Parameter of filter rule
/// </summary>
public BuiltInParameter Parameter { get; private set; }

/// <summary>
/// Filter rule criteria(in String type)
/// </summary>
public String RuleCriteria { get; private set; }

/// <summary>
/// Rule values in string
/// </summary>
public String RuleValue { get; private set; }

/// <summary>
/// Parameter storage type of current FilterRule.
/// </summary>
public StorageType ParamType { get; private set; }

/// <summary>
/// Tolerance of double comparison, valid only when ParamType is double
/// </summary>
public double Epsilon { get; private set; }

/// <summary>
/// Indicates if string comparison is case sensitive, valid only when ParamType is String
/// </summary>
public bool CaseSensitive { get; private set; }
#endregion

#region Class Public Properties

/// <summary>
/// Get ElementId of current parameter
/// </summary>
public ElementId ParamId
{
get { return new ElementId(Parameter); }
}
#endregion

#region Class Public Methods
/// <summary>
/// Create FilterRuleBuilder for String FilterRule
/// </summary>
/// <param name="param">Parameter of FilterRule.</param>
/// <param name="ruleCriteria">Rule criteria.</param>
/// <param name="ruleValue">Rule value.</param>
/// <param name="caseSensitive">Indicates if rule value is case sensitive.</param>
public FilterRuleBuilder(BuiltInParameter param, String ruleCriteria, String ruleValue, bool caseSensitive)
{
InitializeMemebers();
//
// set data with specified values
ParamType = StorageType.String;
Parameter = param;
RuleCriteria = ruleCriteria;
RuleValue = ruleValue;
CaseSensitive = caseSensitive;
}

/// <summary>
/// Create FilterRuleBuilder for double FilterRule
/// </summary>
/// <param name="param">Parameter of FilterRule.</param>
/// <param name="ruleCriteria">Rule criteria.</param>
/// <param name="ruleValue">Rule value.</param>
/// <param name="tolerance">Epsilon for double values comparison.</param>
public FilterRuleBuilder(BuiltInParameter param, String ruleCriteria, double ruleValue, double tolearance)
{
InitializeMemebers();
//
// set data with specified values
ParamType = StorageType.Double;
Parameter = param;
RuleCriteria = ruleCriteria;
RuleValue = ruleValue.ToString();
Epsilon = tolearance;
}

/// <summary>
/// Create FilterRuleBuilder for int FilterRule
/// </summary>
/// <param name="param">Parameter of FilterRule.</param>
/// <param name="ruleCriteria">Rule criteria.</param>
/// <param name="ruleValue">Rule value.</param>
public FilterRuleBuilder(BuiltInParameter param, String ruleCriteria, int ruleValue)
{
InitializeMemebers();
//
// set data with specified values
ParamType = StorageType.Integer;
Parameter = param;
RuleCriteria = ruleCriteria;
RuleValue = ruleValue.ToString();
}

/// <summary>
/// Create FilterRuleBuilder for ElementId FilterRule
/// </summary>
/// <param name="param">Parameter of FilterRule.</param>
/// <param name="ruleCriteria">Rule criteria.</param>
/// <param name="ruleValue">Rule value.</param>
public FilterRuleBuilder(BuiltInParameter param, String ruleCriteria, ElementId ruleValue)
{
InitializeMemebers();
//
// set data with specified values
ParamType = StorageType.ElementId;
Parameter = param;
RuleCriteria = ruleCriteria;
RuleValue = ruleValue.ToString();
}

/// <summary>
/// Create API FilterRule according to sample's FilterRuleBuilder
/// </summary>
/// <returns>API FilterRule converted from current FilterRuleBuilder.</returns>
public FilterRule AsFilterRule()
{
ElementId paramId = new ElementId(Parameter);
if (ParamType == StorageType.String)
{
switch(RuleCriteria)
{
case RuleCriteraNames.BeginWith:
return PFRF.CreateBeginsWithRule(paramId, RuleValue, CaseSensitive);
case RuleCriteraNames.Contains:
return PFRF.CreateContainsRule(paramId, RuleValue, CaseSensitive);
case RuleCriteraNames.EndsWith:
return PFRF.CreateEndsWithRule(paramId, RuleValue, CaseSensitive);
case RuleCriteraNames.Equals_:
return PFRF.CreateEqualsRule(paramId, RuleValue, CaseSensitive);
case RuleCriteraNames.Greater:
return PFRF.CreateGreaterRule(paramId, RuleValue, CaseSensitive);
case RuleCriteraNames.GreaterOrEqual:
return PFRF.CreateGreaterOrEqualRule(paramId, RuleValue, CaseSensitive);
case RuleCriteraNames.Less:
return PFRF.CreateLessRule(paramId, RuleValue, CaseSensitive);
case RuleCriteraNames.LessOrEqual:
return PFRF.CreateLessOrEqualRule(paramId, RuleValue, CaseSensitive);
case RuleCriteraNames.NotBeginWith:
return PFRF.CreateNotBeginsWithRule(paramId, RuleValue, CaseSensitive);
case RuleCriteraNames.NotContains:
return PFRF.CreateNotContainsRule(paramId, RuleValue, CaseSensitive);
case RuleCriteraNames.NotEndsWith:
return PFRF.CreateNotEndsWithRule(paramId, RuleValue, CaseSensitive);
case RuleCriteraNames.NotEquals:
return PFRF.CreateNotEqualsRule(paramId, RuleValue, CaseSensitive);
}
}
else if (ParamType == StorageType.Double)
{
switch(RuleCriteria)
{
case RuleCriteraNames.Equals_:
return PFRF.CreateEqualsRule(paramId, double.Parse(RuleValue), Epsilon);
case RuleCriteraNames.Greater:
return PFRF.CreateGreaterRule(paramId, double.Parse(RuleValue), Epsilon);
case RuleCriteraNames.GreaterOrEqual:
return PFRF.CreateGreaterOrEqualRule(paramId, double.Parse(RuleValue), Epsilon);
case RuleCriteraNames.Less:
return PFRF.CreateLessRule(paramId, double.Parse(RuleValue), Epsilon);
case RuleCriteraNames.LessOrEqual:
return PFRF.CreateLessOrEqualRule(paramId, double.Parse(RuleValue), Epsilon);
case RuleCriteraNames.NotEquals:
return PFRF.CreateNotEqualsRule(paramId, double.Parse(RuleValue), Epsilon);
}
}
else if (ParamType == StorageType.Integer)
{
switch(RuleCriteria)
{
case RuleCriteraNames.Equals_:
return PFRF.CreateEqualsRule(paramId, int.Parse(RuleValue));
case RuleCriteraNames.Greater:
return PFRF.CreateGreaterRule(paramId, int.Parse(RuleValue));
case RuleCriteraNames.GreaterOrEqual:
return PFRF.CreateGreaterOrEqualRule(paramId, int.Parse(RuleValue));
case RuleCriteraNames.Less:
return PFRF.CreateLessRule(paramId, int.Parse(RuleValue));
case RuleCriteraNames.LessOrEqual:
return PFRF.CreateLessOrEqualRule(paramId, int.Parse(RuleValue));
case RuleCriteraNames.NotEquals:
return PFRF.CreateNotEqualsRule(paramId, int.Parse(RuleValue));
}
}
else if (ParamType == StorageType.ElementId)
{
switch(RuleCriteria)
{
case RuleCriteraNames.Equals_:
return PFRF.CreateEqualsRule(paramId, new ElementId(int.Parse(RuleValue)));
case RuleCriteraNames.Greater:
return PFRF.CreateGreaterRule(paramId, new ElementId(int.Parse(RuleValue)));
case RuleCriteraNames.GreaterOrEqual:
return PFRF.CreateGreaterOrEqualRule(paramId, new ElementId(int.Parse(RuleValue)));
case RuleCriteraNames.Less:
return PFRF.CreateLessRule(paramId, new ElementId(int.Parse(RuleValue)));
case RuleCriteraNames.LessOrEqual:
return PFRF.CreateLessOrEqualRule(paramId, new ElementId(int.Parse(RuleValue)));
case RuleCriteraNames.NotEquals:
return PFRF.CreateNotEqualsRule(paramId, new ElementId(int.Parse(RuleValue)));
}
}
//
// Throw exception for others
throw new System.NotImplementedException("This filter rule or criteria is not implemented yet.");
}
#endregion

#region Class Implementations
/// <summary>
/// Make sure all members are initialized with expected values.
/// </summary>
private void InitializeMemebers()
{
Parameter = (BuiltInParameter)(ElementId.InvalidElementId.IntegerValue);
RuleCriteria = String.Empty;
RuleValue = String.Empty;
ParamType = StorageType.None;
Epsilon = 0.0f;
CaseSensitive = false;
}
#endregion
}

/// <summary>
/// This class used to represents data for one API filter.
/// It consists of BuiltInCategory and filter rules
/// </summary>
public sealed class FilterData
{
#region Class Members
/// <summary>
/// Reserves current active document
/// </summary>
Autodesk.Revit.DB.Document m_doc;

/// <summary>
/// BuiltInCategories of filter
/// </summary>
List<BuiltInCategory> m_filterCategories;

/// <summary>
/// Filer rules of filter
/// </summary>
List<FilterRuleBuilder> m_filterRules;
#endregion

#region Public Class Methods
/// <summary>
/// Get BuiltInCategories of filter
/// </summary>
public List<BuiltInCategory> FilterCategories
{
get { return m_filterCategories; }
}

/// <summary>
/// Get BuiltInCategory Ids of filter
/// </summary>
public IList<ElementId> GetCategoryIds()
{
List<ElementId> catIds = new List<ElementId>();
foreach (BuiltInCategory cat in m_filterCategories)
catIds.Add(new ElementId(cat));
return catIds;
}

/// <summary>
/// Set new categories, this method will possibly update existing criteria
/// </summary>
/// <param name="newCatIds">New categories for current filter.</param>
/// <returns>true if categories or criteria are changed; otherwise false.</returns>
/// <remarks>
/// If someone parameter of criteria cannot be supported by new categories,
/// the old criteria will be cleaned and set to empty
/// </remarks>
public bool SetNewCategories(ICollection<ElementId> newCatIds)
{
// do nothing if new categories are equals to old categories
List<BuiltInCategory> newCats = new List<BuiltInCategory>();
foreach (ElementId catId in newCatIds)
newCats.Add((BuiltInCategory)catId.IntegerValue);
if (ListCompareUtility<BuiltInCategory>.Equals(newCats, m_filterCategories))
return false;
m_filterCategories = newCats; // update categories
//
// Check if need to update file rules:
// . if filer rule is empty, do nothing
// . if some parameters of rules cannot be supported by new categories, clean all old rules
ICollection<ElementId> supportParams =
ParameterFilterUtilities.GetFilterableParametersInCommon(m_doc, newCatIds);
foreach (FilterRuleBuilder rule in m_filterRules)
{
if (!supportParams.Contains(new ElementId(rule.Parameter)))
{
m_filterRules.Clear();
break;
}
}
return true;
}

/// <summary>
/// Get FilterRuleBuilder of API filter's rules
/// </summary>
public List<FilterRuleBuilder> RuleData
{
get { return m_filterRules; }
}

/// <summary>
/// Create sample custom FilterData with specified categories and FilterRuleBuilder
/// </summary>
/// <param name="doc">Revit active document.</param>
/// <param name="categories">BuilInCategories of filter.</param>
/// <param name="filterRules">FilterRuleBuilder set of filter.</param>
public FilterData(Autodesk.Revit.DB.Document doc,
ICollection<BuiltInCategory> categories, ICollection<FilterRuleBuilder> filterRules)
{
m_doc = doc;
m_filterCategories = new List<BuiltInCategory>();
m_filterCategories.AddRange(categories);
m_filterRules = new List<FilterRuleBuilder>();
m_filterRules.AddRange(filterRules);
}

/// <summary>
/// Create sample custom FilterData with specified category id and FilterRuleBuilder
/// </summary>
/// <param name="doc">Revit active document.</param>
/// <param name="categories">BuilInCategory ids of filter.</param>
/// <param name="filterRules">FilterRuleBuilder set of filter.</param>
public FilterData(Autodesk.Revit.DB.Document doc,
ICollection<ElementId> categories, ICollection<FilterRuleBuilder> filterRules)
{
m_doc = doc;
m_filterCategories = new List<BuiltInCategory>();
foreach (ElementId catId in categories)
m_filterCategories.Add((BuiltInCategory)catId.IntegerValue);
m_filterRules = new List<FilterRuleBuilder>();
m_filterRules.AddRange(filterRules);
}
#endregion
}

/// <summary>
/// This class define constant strings to map rule criteria
/// </summary>
public sealed class RuleCriteraNames
{
#region Public Class Members
/// <summary>
/// String represents BeginWith criteria
/// </summary>
public const String BeginWith = "begins with";

/// <summary>
/// String represents Contains criteria
/// </summary>
public const String Contains = "contains";

/// <summary>
/// String represents EndWith criteria
/// </summary>
public const String EndsWith = "ends with";

/// <summary>
/// String represents Equals criteria
/// </summary>
public const String Equals_ = "equals";

/// <summary>
/// String represents GreaterThan criteria
/// </summary>
public const String Greater = "is greater than";

/// <summary>
/// String represents GreaterOrEqual criteria
/// </summary>
public const String GreaterOrEqual = "is greater than or equal to";

/// <summary>
/// String represents LessOrEqual criteria
/// </summary>
public const String LessOrEqual = "is less than or equal to";

/// <summary>
/// String represents Less criteria
/// </summary>
public const String Less = "is less than";

/// <summary>
/// String represents NotBeginWith criteria
/// </summary>
public const String NotBeginWith = "does not begin with";

/// <summary>
/// String represents NotContains criteria
/// </summary>
public const String NotContains = "does not contain";

/// <summary>
/// String represents NotEndsWith criteria
/// </summary>
public const String NotEndsWith = "does not end with";

/// <summary>
/// String represents NotEquals criteria
/// </summary>
public const String NotEquals = "does not equal";

/// <summary>
/// Invalid criteria
/// </summary>
public const String Invalid = "n/a";
#endregion

/// <summary>
/// Hide ctor, this class defines only static members, no need to be created
/// </summary>
private RuleCriteraNames() { }

/// <summary>
/// Get all supported criteria(in string) according to StorageType of parameter
/// </summary>
/// <param name="paramType">Parameter type.</param>
/// <returns>String list of criteria supported for specified parameter type.</returns>
public static ICollection<String> Criterions(StorageType paramType)
{
ICollection<String> returns = new List<String>();
//
// all parameter supports following criteria
returns.Add(Equals_);
returns.Add(Greater);
returns.Add(GreaterOrEqual);
returns.Add(LessOrEqual);
returns.Add(Less);
returns.Add(NotEquals);
//
// Only string parameter support criteria below
if (paramType == StorageType.String)
{
returns.Add(BeginWith);
returns.Add(Contains);
returns.Add(EndsWith);
returns.Add(NotBeginWith);
returns.Add(NotContains);
returns.Add(NotEndsWith);
}
return returns;
}
}
}

FilterUtil.cs

//
// (C) Copyright 2003-2019 by Autodesk, Inc.
//
// Permission to use, copy, modify, and distribute this software in
// object code form for any purpose and without fee is hereby granted,
// provided that the above copyright notice appears in all copies and
// that both that copyright notice and the limited warranty and
// restricted rights notice below appear in all supporting
// documentation.
//
// AUTODESK PROVIDES THIS PROGRAM "AS IS" AND WITH ALL FAULTS.
// AUTODESK SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTY OF
// MERCHANTABILITY OR FITNESS FOR A PARTICULAR USE. AUTODESK, INC.
// DOES NOT WARRANT THAT THE OPERATION OF THE PROGRAM WILL BE
// UNINTERRUPTED OR ERROR FREE.
//
// Use, duplication, or disclosure by the U.S. Government is subject to
// restrictions set forth in FAR 52.227-19 (Commercial Computer
// Software - Restricted Rights) and DFAR 252.227-7013(c)(1)(ii)
// (Rights in Technical Data and Computer Software), as applicable.
//

using System;
using System.Text;
using System.Windows.Forms;
using System.Collections;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Diagnostics;

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

namespace Revit.SDK.Samples.ViewFilters.CS
{
/// <summary>
/// One utility class used to access or modify filter related
/// </summary>
public sealed class FiltersUtil
{
/// <summary>
/// Hide ctor, this class defines only static members, no need to be created
/// </summary>
private FiltersUtil() { }

/// <summary>
/// Get all view filters(ParameterFilterElement) within current document
/// </summary>
/// <returns>All existing filters.</returns>
public static ICollection<ParameterFilterElement> GetViewFilters(Autodesk.Revit.DB.Document doc)
{
ElementClassFilter filter = new ElementClassFilter(typeof(ParameterFilterElement));
FilteredElementCollector collector = new FilteredElementCollector(doc);
return collector.WherePasses(filter).ToElements()
.Cast<ParameterFilterElement>().ToList<ParameterFilterElement>();
}

/// <summary>
/// Convert FilterRule to our custom FilterRuleBuilder which will be displayed in form controls
/// </summary>
/// <param name="param">Parameter to which the FilterRule is applied.</param>
/// <param name="rule">FilterRule to be converted.</param>
/// <returns>Custom FilterRuleBuilder data converted from FilterRule</returns>
public static FilterRuleBuilder CreateFilterRuleBuilder(BuiltInParameter param, FilterRule rule)
{
// Maybe FilterRule is inverse rule, we need to find its inner rule(FilterValueRule)
// Note that the rule may be inversed more than once.
bool inverted = false;
FilterRule innerRule = ReflectToInnerRule(rule, out inverted);
if (innerRule is FilterStringRule)
{
FilterStringRule strRule = innerRule as FilterStringRule;
FilterStringRuleEvaluator evaluator = strRule.GetEvaluator();
return new FilterRuleBuilder(param, GetEvaluatorCriteriaName(evaluator, inverted), strRule.RuleString, strRule.RuleString.ToLower() == strRule.RuleString ? false : true);
}
else if (innerRule is FilterDoubleRule)
{
FilterDoubleRule dbRule = innerRule as FilterDoubleRule;
FilterNumericRuleEvaluator evaluator = dbRule.GetEvaluator();
return new FilterRuleBuilder(param, GetEvaluatorCriteriaName(evaluator, inverted), dbRule.RuleValue, dbRule.Epsilon);
}
else if (innerRule is FilterIntegerRule)
{
FilterIntegerRule intRule = innerRule as FilterIntegerRule;
FilterNumericRuleEvaluator evaluator = intRule.GetEvaluator();
return new FilterRuleBuilder(param, GetEvaluatorCriteriaName(evaluator, inverted), intRule.RuleValue);
}
else if (innerRule is FilterElementIdRule)
{
FilterElementIdRule idRule = innerRule as FilterElementIdRule;
FilterNumericRuleEvaluator evaluator = idRule.GetEvaluator();
return new FilterRuleBuilder(param, GetEvaluatorCriteriaName(evaluator, inverted), idRule.RuleValue);
}
//
// for other rule, not supported yet
throw new System.NotImplementedException("The filter rule is not recognizable and supported yet!");
}

/// <summary>
/// Get criteria(in string) from String Evaluator
/// </summary>
/// <param name="fsre">String Evaluator used to retrieve the criteria.</param>
/// <param name="inverted">Indicates whether rule to which Evaluator belong is inverse rule.
/// If inverted is true, inverse criteria for this evaluator will be returned. </param>
/// <returns>criteria of this Evaluator.</returns>
static string GetEvaluatorCriteriaName(FilterStringRuleEvaluator fsre, bool inverted)
{
// indicate if inverse criteria should be returned
bool isInverseRule = inverted;
if (fsre is FilterStringBeginsWith)
return (isInverseRule ? RuleCriteraNames.NotBeginWith : RuleCriteraNames.BeginWith);
else if (fsre is FilterStringContains)
return (isInverseRule ? RuleCriteraNames.NotContains : RuleCriteraNames.Contains);
else if (fsre is FilterStringEndsWith)
return (isInverseRule ? RuleCriteraNames.NotEndsWith : RuleCriteraNames.EndsWith);
else if (fsre is FilterStringEquals)
return (isInverseRule ? RuleCriteraNames.NotEquals : RuleCriteraNames.Equals_);
else if (fsre is FilterStringGreater)
return (isInverseRule ? RuleCriteraNames.LessOrEqual : RuleCriteraNames.Greater);
else if (fsre is FilterStringGreaterOrEqual)
return (isInverseRule ? RuleCriteraNames.Less : RuleCriteraNames.GreaterOrEqual);
else if (fsre is FilterStringLess)
return (isInverseRule ? RuleCriteraNames.GreaterOrEqual : RuleCriteraNames.Less);
else if (fsre is FilterStringLessOrEqual)
return (isInverseRule ? RuleCriteraNames.Greater : RuleCriteraNames.LessOrEqual);
else
return RuleCriteraNames.Invalid;
}

/// <summary>
/// Get criteria(in string) from Numeric Evaluator
/// </summary>
/// <param name="fsre">String Evaluator used to retrieve the criteria.</param>
/// <param name="inverted">Indicates whether rule to which Evaluator belong is inverse rule.
/// If inverted is true, inverse criteria for this evaluator will be returned. </param>
/// <returns>criteria of this Evaluator.</returns>
static string GetEvaluatorCriteriaName(FilterNumericRuleEvaluator fsre, bool inverted)
{
// indicate if inverse criteria should be returned
bool isInverseRule = inverted;
if (fsre is FilterNumericEquals)
return (isInverseRule ? RuleCriteraNames.NotEquals : RuleCriteraNames.Equals_);
else if (fsre is FilterNumericGreater)
return (isInverseRule ? RuleCriteraNames.LessOrEqual : RuleCriteraNames.Greater);
else if (fsre is FilterNumericGreaterOrEqual)
return (isInverseRule ? RuleCriteraNames.Less : RuleCriteraNames.GreaterOrEqual);
else if (fsre is FilterNumericLess)
return (isInverseRule ? RuleCriteraNames.GreaterOrEqual : RuleCriteraNames.Less);
else if (fsre is FilterNumericLessOrEqual)
return (isInverseRule ? RuleCriteraNames.Greater : RuleCriteraNames.LessOrEqual);
else
return RuleCriteraNames.Invalid;
}

/// <summary>
/// Reflect filter rule to its inner rule, the final inner rule is FilterValueRule for this sample
/// </summary>
/// <param name="srcRule">Source filter to be checked.</param>
/// <param name="inverted">Indicates if source rule is inverse rule mapping to its inner rule.
/// Note that the rule may be inversed more than once, if inverse time is odd(1, 3, 5...), the inverted will be true.
/// If inverse time is even(0, 2, 4...), the inverted will be false. </param>
/// <returns>Inner rule of source rule, the inner rule is FilterValueRule type for this sample.</returns>
public static FilterRule ReflectToInnerRule(FilterRule srcRule, out bool inverted)
{
if (srcRule is FilterInverseRule)
{
inverted = true;
FilterRule innerRule = (srcRule as FilterInverseRule).GetInnerRule();
bool invertedAgain = false;
FilterRule returnRule = ReflectToInnerRule(innerRule, out invertedAgain);
if (invertedAgain)
inverted = false;
return returnRule;
}
else
{
inverted = false;
return srcRule;
}
}

/// <summary>
/// Create an ElementFilter representing a conjunction ("ANDing together") of FilterRules.
/// </summary>
/// <param name="filterRules">A list of FilterRules</param>
/// <returns>The ElementFilter.</returns>
public static ElementFilter CreateElementFilterFromFilterRules(IList<FilterRule> filterRules)
{
// KEEP THIS FUNCTION SYNCHRONIZED WITH GetConjunctionOfFilterRulesFromElementFilter!!!

// We use a LogicalAndFilter containing one ElementParameterFilter
// for each FilterRule. We could alternatively create a single
// ElementParameterFilter containing the entire list of FilterRules.
IList<ElementFilter> elemFilters = new List<ElementFilter>();
foreach (FilterRule filterRule in filterRules)
{
ElementParameterFilter elemParamFilter = new ElementParameterFilter(filterRule);
elemFilters.Add(elemParamFilter);
}
LogicalAndFilter elemFilter = new LogicalAndFilter(elemFilters);

return elemFilter;
} // CreateElementFilterFromFilterRules

/// <summary>
/// Given an ElementFilter representing a conjunction of FilterRules, return the list of FilterRules.
/// </summary>
/// <param name="elemFilter">An ElementFilter representing a conjunction of FilterRules.</param>
/// <returns>A list of FilterRules whose conjunction the ElementFilter represents.</returns>
public static IList<FilterRule> GetConjunctionOfFilterRulesFromElementFilter(ElementFilter elemFilter)
{
// KEEP THIS FUNCTION SYNCHRONIZED WITH CreateElementFilterFromFilterRules!!!

// The ElementFilter is assumed to have been created by CreateElementFilterFromFilterRules,
// which creates a LogicalAndFilter with each child being an ElementParameterFilter containing
// just one FilterRule.
LogicalAndFilter logicalAndFilter = elemFilter as LogicalAndFilter;
if (null == logicalAndFilter)
return null; // Error

IList<ElementFilter> childElemFilters = logicalAndFilter.GetFilters();
int numChildElemFilters = childElemFilters.Count;
if (0 == numChildElemFilters)
return null; // Error

IList<FilterRule> filterRules = new List<FilterRule>();
foreach (ElementFilter childElemFilter in childElemFilters)
{
ElementParameterFilter elemParamFilter = childElemFilter as ElementParameterFilter;
if (null == elemParamFilter)
return null;
IList<FilterRule> rules = elemParamFilter.GetRules();
if (1 != rules.Count)
return null;
filterRules.Add(rules[0]);
}

return filterRules;
} // GetConjunctionOfFilterRulesFromElementFilter

} // class FiltersUtil
} // namespace