From 5166d6e1b215ada7af552166c1dd39ce3901a7ea Mon Sep 17 00:00:00 2001 From: Adam Sobieski Date: Mon, 3 Aug 2026 15:52:28 +0200 Subject: [PATCH 1/2] Return fallback Level and update parameter ordering Level.cs: introduce a local Level variable and change lookup flow to prefer LevelParameter and family host, then fall back to Document.LevelBelow(location) instead of returning null. LevelParameter.cs: adjust LINQ selection to use ThenByDescending on IsReadOnly and call FirstOrDefault() (remove predicate) so the candidate is chosen via ordered ranking (valid ElementIds first, then read-only ordering). This makes level resolution more robust and centralizes parameter selection logic. --- Revit_Core_Engine/Query/Level.cs | 14 +++++++++++--- Revit_Core_Engine/Query/LevelParameter.cs | 9 ++++++--- 2 files changed, 17 insertions(+), 6 deletions(-) diff --git a/Revit_Core_Engine/Query/Level.cs b/Revit_Core_Engine/Query/Level.cs index 48b3ae5c1..1ba823998 100644 --- a/Revit_Core_Engine/Query/Level.cs +++ b/Revit_Core_Engine/Query/Level.cs @@ -49,17 +49,25 @@ public static Level Level(this Element element) if (levelId.Value() != -1) return doc.GetElement(levelId) as Level; + Level level = null; + // Second priority: Check level parameters (LevelParameter or BaseLevelParameter) Parameter levelParameter = element.LevelParameter() ?? element.BaseLevelParameter(); if (levelParameter != null) - return doc.GetElement(levelParameter.AsElementId()) as Level; + level = doc.GetElement(levelParameter?.AsElementId()) as Level; + + if (level != null) + return level; // Third priority: Check if element is work plane-based and hosted on a level if (element.IsWorkPlaneLevelBased()) - return (element as FamilyInstance)?.Host as Level; + level = (element as FamilyInstance)?.Host as Level; + + if (level == null) + level = element.Document.LevelBelow(element.LocationPoint()); // No level found - return null; + return level; } /***************************************************/ diff --git a/Revit_Core_Engine/Query/LevelParameter.cs b/Revit_Core_Engine/Query/LevelParameter.cs index 6cffd7f3d..6edde8ff6 100644 --- a/Revit_Core_Engine/Query/LevelParameter.cs +++ b/Revit_Core_Engine/Query/LevelParameter.cs @@ -45,7 +45,8 @@ public static Parameter LevelParameter(this Element element) .Select(x => element.get_Parameter(x)) .Where(x => x != null) .OrderByDescending(x => x.AsElementId().Value() != -1) // Valid ElementIds first - .FirstOrDefault(x => !x.IsReadOnly); + .ThenByDescending(x => x.IsReadOnly) + .FirstOrDefault(); } /***************************************************/ @@ -62,7 +63,8 @@ public static Parameter BaseLevelParameter(this Element element) .Select(x => element.get_Parameter(x)) .Where(x => x != null) .OrderByDescending(x => x.AsElementId().Value() != -1) // Valid ElementIds first - .FirstOrDefault(x => !x.IsReadOnly); + .ThenByDescending(x => x.IsReadOnly) + .FirstOrDefault(); } /***************************************************/ @@ -79,7 +81,8 @@ public static Parameter TopLevelParameter(this Element element) .Select(x => element.get_Parameter(x)) .Where(x => x != null) .OrderByDescending(x => x.AsElementId().Value() != -1) // Valid ElementIds first - .FirstOrDefault(x => !x.IsReadOnly); + .ThenByDescending(x => x.IsReadOnly) + .FirstOrDefault(); } /***************************************************/ From 717edd3bf4e9326c19eab691e81571b793d1d4ef Mon Sep 17 00:00:00 2001 From: Adam Sobieski Date: Mon, 3 Aug 2026 16:51:58 +0200 Subject: [PATCH 2/2] Null checks added --- Revit_Core_Engine/Query/Level.cs | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/Revit_Core_Engine/Query/Level.cs b/Revit_Core_Engine/Query/Level.cs index 1ba823998..6db691dd9 100644 --- a/Revit_Core_Engine/Query/Level.cs +++ b/Revit_Core_Engine/Query/Level.cs @@ -42,31 +42,32 @@ public static Level Level(this Element element) if (element == null) return null; + Level level = null; Document doc = element.Document; ElementId levelId = element.LevelId; // First priority: Check LevelId property (most direct way to get level) if (levelId.Value() != -1) - return doc.GetElement(levelId) as Level; - - Level level = null; + level = doc.GetElement(levelId) as Level; + if (level != null) + return level; // Second priority: Check level parameters (LevelParameter or BaseLevelParameter) Parameter levelParameter = element.LevelParameter() ?? element.BaseLevelParameter(); if (levelParameter != null) level = doc.GetElement(levelParameter?.AsElementId()) as Level; - if (level != null) return level; // Third priority: Check if element is work plane-based and hosted on a level if (element.IsWorkPlaneLevelBased()) level = (element as FamilyInstance)?.Host as Level; + if (level != null) + return level; - if (level == null) - level = element.Document.LevelBelow(element.LocationPoint()); + // Fourth priority: Use the LevelBelow method to find the level below the element's location point + level = element.Document.LevelBelow(element.LocationPoint()); - // No level found return level; }