From 62a5678d3a9b594a578a706b1e8d12be56509440 Mon Sep 17 00:00:00 2001 From: Jorgen Dahl Date: Thu, 2 Mar 2017 08:46:56 -0500 Subject: [PATCH 1/4] Initial commit after basic testing --- src/Libraries/RevitNodes/Elements/Element.cs | 25 ++++++++++++++++---- 1 file changed, 20 insertions(+), 5 deletions(-) diff --git a/src/Libraries/RevitNodes/Elements/Element.cs b/src/Libraries/RevitNodes/Elements/Element.cs index bf1aae2eb..14b03f608 100644 --- a/src/Libraries/RevitNodes/Elements/Element.cs +++ b/src/Libraries/RevitNodes/Elements/Element.cs @@ -310,6 +310,19 @@ public void Tessellate(IRenderPackage package, TessellationParameters parameters // or transactions and which must necessarily be threaded in a specific way. } + + private Autodesk.Revit.DB.Parameter GetParameterByName(string parameterName) + { + var allParams = + InternalElement.Parameters.Cast() + .Where(x => x.Definition.Name == parameterName) + .OrderBy(x => x.Id.IntegerValue); + + var param = allParams.FirstOrDefault(x => x.IsReadOnly == false) ?? allParams.FirstOrDefault(); + + return param; + } + /// /// Get the value of one of the element's parameters. /// @@ -318,14 +331,15 @@ public void Tessellate(IRenderPackage package, TessellationParameters parameters public object GetParameterValueByName(string parameterName) { - var param = +// var param = // We don't use Element.GetOrderedParameters(), it only returns ordered parameters // as show in the UI - InternalElement.Parameters.Cast() +// InternalElement.Parameters.Cast() // Element.Parameters returns a differently ordered list on every invocation. // We must sort it to get sensible results. - .OrderBy(x => x.Id.IntegerValue) - .FirstOrDefault(x => x.Definition.Name == parameterName); +// .OrderBy(x => x.Id.IntegerValue) +// .FirstOrDefault(x => x.Definition.Name == parameterName); + var param = GetParameterByName(parameterName); if (param == null || !param.HasValue) return string.Empty; @@ -382,7 +396,8 @@ public Element OverrideInView(Revit.Filter.OverrideGraphicSettings overrides, bo /// The value. public Element SetParameterByName(string parameterName, object value) { - var param = InternalElement.Parameters.Cast().FirstOrDefault(x => x.Definition.Name == parameterName); +// var param = InternalElement.Parameters.Cast().FirstOrDefault(x => x.Definition.Name == parameterName); + var param = GetParameterByName(parameterName); if (param == null) throw new Exception(Properties.Resources.ParameterNotFound); From d11403669b42bf2872c7f317d273f1fe7c59b39f Mon Sep 17 00:00:00 2001 From: Jorgen Dahl Date: Thu, 2 Mar 2017 08:52:42 -0500 Subject: [PATCH 2/4] Add comment --- src/Libraries/RevitNodes/Elements/Element.cs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/Libraries/RevitNodes/Elements/Element.cs b/src/Libraries/RevitNodes/Elements/Element.cs index 14b03f608..038f795c1 100644 --- a/src/Libraries/RevitNodes/Elements/Element.cs +++ b/src/Libraries/RevitNodes/Elements/Element.cs @@ -311,6 +311,11 @@ public void Tessellate(IRenderPackage package, TessellationParameters parameters } + /// + /// Get a parameter by name of an element + /// + /// The name of the parameter. + /// private Autodesk.Revit.DB.Parameter GetParameterByName(string parameterName) { var allParams = From 790c520cf296a939f4e625bb06502a0241ec678f Mon Sep 17 00:00:00 2001 From: Jorgen Dahl Date: Thu, 2 Mar 2017 09:38:30 -0500 Subject: [PATCH 3/4] Update comments --- src/Libraries/RevitNodes/Elements/Element.cs | 33 ++++++++++++++------ 1 file changed, 23 insertions(+), 10 deletions(-) diff --git a/src/Libraries/RevitNodes/Elements/Element.cs b/src/Libraries/RevitNodes/Elements/Element.cs index 038f795c1..0c7b26dfa 100644 --- a/src/Libraries/RevitNodes/Elements/Element.cs +++ b/src/Libraries/RevitNodes/Elements/Element.cs @@ -318,6 +318,29 @@ public void Tessellate(IRenderPackage package, TessellationParameters parameters /// private Autodesk.Revit.DB.Parameter GetParameterByName(string parameterName) { + // + // Parameter names are not unique on a given element. There are several valid cases where + // duplicated parameter names can be found in the Parameter Set. + // + // The most common ones are: + // + // 1. Multiple built-in parameters with the same name + // This is a common implementation pattern when a different parameter behavior is wanted + // for different scopes. For example, lets say that you want a parameter to be writable + // in the property palette but read-only in a schedule view. The easiest way to accomplish + // this would be to add two parameters. One that is read-write and one that is read-only. + // These parameters will both have the same name and they will share the same getter. + // + // 2. Built-in parameters and User parameters with the same name + // This happens when a loadable family defines a user parameter with the same name + // as a built-in parameter. + // + // Currently, we try to resolve this and get consistent results by + // 1. Get all parameters for the given name + // 2. Sort parameters by ElementId - This will give us built-in parameters first (ID's for built-ins are always < -1) + // 3. If it exist: Use the first writable parameter + // 4. Otherwise: Use the first read-only parameter + // var allParams = InternalElement.Parameters.Cast() .Where(x => x.Definition.Name == parameterName) @@ -335,15 +358,6 @@ private Autodesk.Revit.DB.Parameter GetParameterByName(string parameterName) /// public object GetParameterValueByName(string parameterName) { - -// var param = - // We don't use Element.GetOrderedParameters(), it only returns ordered parameters - // as show in the UI -// InternalElement.Parameters.Cast() - // Element.Parameters returns a differently ordered list on every invocation. - // We must sort it to get sensible results. -// .OrderBy(x => x.Id.IntegerValue) -// .FirstOrDefault(x => x.Definition.Name == parameterName); var param = GetParameterByName(parameterName); if (param == null || !param.HasValue) @@ -401,7 +415,6 @@ public Element OverrideInView(Revit.Filter.OverrideGraphicSettings overrides, bo /// The value. public Element SetParameterByName(string parameterName, object value) { -// var param = InternalElement.Parameters.Cast().FirstOrDefault(x => x.Definition.Name == parameterName); var param = GetParameterByName(parameterName); if (param == null) From 341387b57c1edfdeb1fc15ba4db5d8dcfaeefbc3 Mon Sep 17 00:00:00 2001 From: Jorgen Dahl Date: Thu, 2 Mar 2017 15:44:00 -0500 Subject: [PATCH 4/4] Use CompareOrdinal instead of == --- src/Libraries/RevitNodes/Elements/Element.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Libraries/RevitNodes/Elements/Element.cs b/src/Libraries/RevitNodes/Elements/Element.cs index 0c7b26dfa..81eb4a986 100644 --- a/src/Libraries/RevitNodes/Elements/Element.cs +++ b/src/Libraries/RevitNodes/Elements/Element.cs @@ -343,7 +343,7 @@ private Autodesk.Revit.DB.Parameter GetParameterByName(string parameterName) // var allParams = InternalElement.Parameters.Cast() - .Where(x => x.Definition.Name == parameterName) + .Where(x => string.CompareOrdinal(x.Definition.Name, parameterName) == 0) .OrderBy(x => x.Id.IntegerValue); var param = allParams.FirstOrDefault(x => x.IsReadOnly == false) ?? allParams.FirstOrDefault();