Skip to content

Add SheetCollection UI node and Elements wrapper for Revit 2025+#82

Merged
johnpierson merged 3 commits intomasterfrom
copilot/reimplement-sheetsui-and-introduce-sheetcollection
Jan 12, 2026
Merged

Add SheetCollection UI node and Elements wrapper for Revit 2025+#82
johnpierson merged 3 commits intomasterfrom
copilot/reimplement-sheetsui-and-introduce-sheetcollection

Conversation

Copy link
Contributor

Copilot AI commented Jan 12, 2026

Implements SheetCollection dropdown selector and query methods for Revit 2025+, where the SheetCollection API was introduced. Also restores the deprecated Sheets UI node.

Changes

  • RhythmUI/SheetCollection.cs: Dropdown node for selecting sheet collections from project

    • Returns null with user message for Revit < 2025
    • Uses FilteredElementCollector with OfClass(typeof(SheetCollection)) for R25+
    • Outputs selected collection via ElementSelector.ByElementId
  • RhythmRevit/Revit/Elements/SheetCollection.cs: Query wrapper with Sheets() method

    • Filters all ViewSheet elements by SheetCollectionId property (R25+ only)
    • Orders by sheet number, then name
    • Returns empty list for Revit < 2025
  • RhythmUI/SheetsUI.cs: Removed [NodeDeprecated] attribute

All implementations use #if R25_OR_GREATER preprocessor directives for version-safe compilation across Revit 2020-2026.

// R25+ conditional compilation pattern
#if !R25_OR_GREATER
    return new List<global::Revit.Elements.Element>();
#else
    var sheetsInCollection = allSheets
        .Where(sheet => sheet.SheetCollectionId == collectionId)
        .Select(sheet => sheet.ToDSType(false));
#endif
Original prompt

This section details on the original issue you should resolve

<issue_title>Reimplement SheetsUI and Introduce SheetCollection.cs in RhythmUI</issue_title>
<issue_description>What is the problem that needs solving?
Need to implement the following in RhythmUI as a SheetCollection.cs

using System.Collections.Generic;
using System.Linq;
using Autodesk.Revit.DB;
using CoreNodeModels;
using Dynamo.Graph.Nodes;
using ProtoCore.AST.AssociativeAST;
using RevitServices.Persistence;
using DSRevitNodesUI;
using Newtonsoft.Json;

namespace RhythmUI
{
    [NodeName("Sheet Collections")]
    [NodeCategory("Rhythm.Revit.Selection.Selection")]
    [NodeDescription("Allows you to select a sheet collection from all sheet collections in your project.")]
    [IsDesignScriptCompatible]
    public class SheetCollection : RevitDropDownBase
    {
        private const string noCollections = "No Sheet Collections available in project.";
        private const string outputName = "SheetCollection";
        public SheetCollection() : base(outputName) { }
        [JsonConstructor]
        public SheetCollection(IEnumerable<PortModel> inPorts, IEnumerable<PortModel> outPorts) : base(outputName, inPorts, outPorts)
        {
        }
        protected override SelectionState PopulateItemsCore(string currentSelection)
        {
            Items.Clear();
            var doc = DocumentManager.Instance.CurrentDBDocument;
            
#if !R25_OR_GREATER
            // SheetCollection class is only available in R25+
            Items.Add(new DynamoDropDownItem("Sheet Collections require Revit 2025 or later.", null));
            SelectedIndex = 0;
            return SelectionState.Done;
#else
            // Find all SheetCollection elements in the project
            var collector = new FilteredElementCollector(doc);
            collector.OfClass(typeof(Autodesk.Revit.DB.SheetCollection));
            var elements = collector.ToElements().Cast<Autodesk.Revit.DB.SheetCollection>();
            
            if (!elements.Any())
            {
                Items.Add(new DynamoDropDownItem(noCollections, null));
                SelectedIndex = 0;
                return SelectionState.Done;
            }
            
            Items = elements.Select(x => new DynamoDropDownItem(x.Name, x)).OrderBy(x => x.Name).ToObservableCollection();
            return SelectionState.Restore;
#endif
        }
        public override IEnumerable<AssociativeNode> BuildOutputAst(List<AssociativeNode> inputAstNodes)
        {
            if (Items.Count == 0 ||
                Items[0].Name == noCollections ||
                Items[0].Name == "Sheet Collections require Revit 2025 or later." ||
                SelectedIndex == -1)
            {
                return new[] { AstFactory.BuildAssignment(GetAstIdentifierForOutputIndex(0), AstFactory.BuildNullNode()) };
            }

#if !R25_OR_GREATER
            return new[] { AstFactory.BuildAssignment(GetAstIdentifierForOutputIndex(0), AstFactory.BuildNullNode()) };
#else
            var selectedCollection = Items[SelectedIndex].Item as Autodesk.Revit.DB.SheetCollection;
            if (selectedCollection == null)
            {
                return new[] { AstFactory.BuildAssignment(GetAstIdentifierForOutputIndex(0), AstFactory.BuildNullNode()) };
            }

            var node = AstFactory.BuildFunctionCall(
                "Revit.Elements.ElementSelector",
                "ByElementId",
                new List<AssociativeNode>
                {
                    AstFactory.BuildIntNode(selectedCollection.Id.Value)
                });
            return new[] { AstFactory.BuildAssignment(GetAstIdentifierForOutputIndex(0), node) };
#endif
        }
    }
}

Also need SheetCollection.cs in Revit>Elements with this:

using System;
using System.Collections.Generic;
using System.Linq;
using Autodesk.Revit.DB;
using Autodesk.DesignScript.Runtime;
using Dynamo.Graph.Nodes;
using Revit.Elements;
using RevitServices.Persistence;

namespace Rhythm.Revit.Elements
{
    /// <summary>
    /// Wrapper class for sheet collections.
    /// </summary>
    public class SheetCollection
    {
        private SheetCollection()
        {
        }

        /// <summary>
        /// Gets all sheets in the specified sheet collection.
        /// </summary>
        /// <param name="sheetCollection">The sheet collection to get sheets from.</param>
        /// <returns name="Sheets">The sheets in the collection.</returns>
        /// <search>
        /// sheet collection, sheets, rhythm
        /// </search>
        [NodeCategory("Query")]
        public static IEnumerable<global::Revit.Elements.Element> Sheets(global::Revit.Elements.Element sheetCollection)
        {
            if (sheetCollection == null)
            {
                return new List<global::Revit.Elements.Element>();
            }

#if !R25_OR_GREATER
            // SheetCollection class is only available in R25+
            r...

</details>



<!-- START COPILOT CODING AGENT SUFFIX -->

- Fixes johnpierson/RhythmForDynamo#81

<!-- START COPILOT CODING AGENT TIPS -->
---

💬 We'd love your input! Share your thoughts on Copilot coding agent in our [2 minute survey](https://gh.io/copilot-coding-agent-survey).

Copilot AI and others added 2 commits January 12, 2026 19:09
…om SheetsUI

Co-authored-by: johnpierson <15744724+johnpierson@users.noreply.github.com>
Co-authored-by: johnpierson <15744724+johnpierson@users.noreply.github.com>
Copilot AI changed the title [WIP] Reimplement SheetsUI and introduce SheetCollection.cs in RhythmUI Add SheetCollection UI node and Elements wrapper for Revit 2025+ Jan 12, 2026
Copilot AI requested a review from johnpierson January 12, 2026 19:13
@johnpierson johnpierson marked this pull request as ready for review January 12, 2026 20:01
Copy link
Owner

@johnpierson johnpierson left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lgtm mr copilot

@johnpierson johnpierson merged commit 97a9f03 into master Jan 12, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants