Back to Devexpress

Export Blazor TreeList Data to XLS/XLSX

blazor-405491-components-treelist-export-excel-export.md

latest30.2 KB
Original Source

Export Blazor TreeList Data to XLS/XLSX

  • Jan 20, 2026
  • 13 minutes to read

Call the ExportToXlsAsync/ExportToXlsxAsync method to export TreeList data to an Excel format. The output table maintains sort settings and summaries. You can save the result to a stream or download it to the client. The method parameter allows you to configure export settings and customize the sheet’s appearance.

Run Demo: TreeList - Export Data

You can also export TreeList data to PDF or CSV formats.

Limitations and Specifics

  • Content of templates is not exported.
  • Excel permits up to seven nesting levels in outlines. Deeper nesting levels are exported at the seventh nesting level.
  • The TreeList exports custom summaries (implemented in the CustomSummary event) as plain text.
  • Data columns anchored to the right edge become regular columns, while columns anchored to the component’s left edge remain frozen.
  • CSS classes applied to the TreeList and its elements do not affect the exported document’s appearance. Handle the CustomizeCell event to customize the output table.
  • In on demand data loading mode, an export operation forces the component to load all data.

If the TreeList is bound to a GridDevExtremeDataSource object, the following limitations apply:

Refer to the following articles for information about Microsoft Excel limitations:

Prevent a Column from Being Exported

The TreeList component exports data from all data columns. Set a column’s ExportEnabled property to false to exclude it from data export:

razor
@inject SpaceObjectDataProvider SpaceObjectDataProvider

<DxButton Text="Export to XLSX" Click="ExportXlsx_Click" />
<DxTreeList @ref="TreeList" Data="TreeListData" ChildrenFieldName="Satellites">
    <Columns>
        <DxTreeListDataColumn FieldName="Name" />
        <DxTreeListDataColumn FieldName="TypeOfObject" Caption="Type" />
        <DxTreeListDataColumn FieldName="Mass10pow21kg" Caption="Mass, kg" DisplayFormat="N2">
            <HeaderCaptionTemplate>Mass, 10<sup>21</sup> &#215; kg</HeaderCaptionTemplate>
        </DxTreeListDataColumn>
        <DxTreeListDataColumn FieldName="MeanRadiusInKM" ExportEnabled="false" Caption="Radius, km" DisplayFormat="N2" />
        <DxTreeListDataColumn FieldName="Volume10pow9KM3" Caption="Volume, km³" DisplayFormat="N2" />
        <DxTreeListDataColumn FieldName="SurfaceGravity" ExportEnabled="false" DisplayFormat="N2" />
    </Columns>
</DxTreeList>

@code {
    ITreeList TreeList { get; set; }
    object TreeListData { get; set; }

    protected override async Task OnInitializedAsync() {
        TreeListData = SpaceObjectDataProvider.GenerateData();
    }
    async Task ExportXlsx_Click() {
        await TreeList.ExportToXlsxAsync("ExportResult");
    }
}
csharp
using System.Collections.Generic;

public class SpaceObject {
    public string Name { get; set; }
    public double MeanRadiusInKM { get; set; }
    public double Volume10pow9KM3 { get; set; }
    public double Mass10pow21kg { get; set; }
    public double Density { get; set; }
    public double SurfaceGravity { get; set; }
    public string TypeOfObject { get; set; }
    public List<SpaceObject> Satellites { get; set; }
    public SpaceObject(
        string name,
        double meanRadiusInKM,
        double volume10pow9KM3,
        double mass10pow21kg,
        double density,
        double surfaceGravity,
        string typeOfObject,
        List<SpaceObject> satellites = null
    ) {
        Name = name;
        MeanRadiusInKM = meanRadiusInKM;
        Volume10pow9KM3 = volume10pow9KM3;
        Mass10pow21kg = mass10pow21kg;
        Density = density;
        SurfaceGravity = surfaceGravity;
        TypeOfObject = typeOfObject;
        Satellites = satellites ?? new List<SpaceObject>();
    }
}
csharp
public class SpaceObjectDataProvider {
    public List<SpaceObject> GenerateData() {
        return new List<SpaceObject>() {
            new SpaceObject("Sun", 696000, 1412000000, 1989100000, 1.409, 274.0, "Star", new List<SpaceObject>() {
                new SpaceObject("Mercury", 2439.7, 60.83, 330.2, 5.43, 3.7, "Planet"),
                new SpaceObject("Venus", 6051.8, 928.43, 4868.5, 5.24, 8.872, "Planet"),
                new SpaceObject("Earth", 6371.0, 1083.21, 5973.6, 5.515, 9.78033, "Planet", new List<SpaceObject> () {
                    new SpaceObject("Moon", 1737.1, 21.958, 73.5, 3.3464, 1.625, "Satellite")
                }),
                new SpaceObject("Mars", 3390.0, 163.18, 641.85, 3.94, 3.7, "Planet"),
                new SpaceObject("Jupiter", 69911, 1431280, 1898600, 1.33, 24.79, "Planet", new List<SpaceObject>() {
                    new SpaceObject("Ganymede", 2631.2, 76.30, 148.2, 1.936, 1.428, "Satellite"),
                    new SpaceObject("Callisto", 2410.3, 58.65, 107.6, 1.83, 1.23603, "Satellite"),
                    new SpaceObject("Io", 1821.5, 25.32, 89.3, 3.528, 1.797, "Satellite"),
                    new SpaceObject("Europa", 1561, 15.93, 48, 3.01, 1.316, "Satellite"),
                }),
                new SpaceObject("Saturn", 58232, 827130, 568460, 0.70, 10.445, "Planet", new List<SpaceObject>() {
                    new SpaceObject("Titan", 2576, 71.52, 134.5, 1.88, 1.354, "Satellite"),
                    new SpaceObject("Rhea", 764.4, 1.87, 2.3166, 1.23, 0.26, "Satellite"),
                    new SpaceObject("Iapetus", 736, 1.55, 1.9739, 1.08, 0.223, "Satellite"),
                    new SpaceObject("Dione", 561.6, 0.73, 1.096, 1.48, 0.232, "Satellite"),
                    new SpaceObject("Tethys", 533, 0.624, 0.6173, 1.15, 0.145, "Satellite"),
                    new SpaceObject("Enceladus", 252.1, 0.067, 0.108, 1.61, 0.111, "Satellite"),
                    new SpaceObject("Mimas", 198.3, 0.033, 0.03749, 1.15, 0.06363, "Satellite")
                }),
                new SpaceObject("Uranus", 25362, 68340, 86832, 1.30, 8.87, "Planet", new List<SpaceObject>() {
                    new SpaceObject("Titania", 788.9, 2.06, 3.526, 1.72, 0.378, "Satellite"),
                    new SpaceObject("Oberon", 761.4, 1.85, 3.014, 1.63, 0.347, "Satellite"),
                    new SpaceObject("Umbriel", 584.7, 0.84, 1.2, 1.4, 0.234, "Satellite"),
                    new SpaceObject("Ariel", 578.9, 0.81, 1.35, 1.67, 0.269, "Satellite"),
                    new SpaceObject("Miranda", 235.8, 0.055, 0.0659, 1.20, 0.07910375, "Satellite"),
                }),
                new SpaceObject("Neptune", 24622, 62540, 102430, 1.76, 11.15, "Planet", new List<SpaceObject>() {
                    new SpaceObject("Triton", 1353.4, 10.38, 21.5, 2.061, 0.782, "Satellite"),
                    new SpaceObject("Proteus", 210, 0.038, 0.050, 1.3, 0.0666, "Satellite"),
                }),
                new SpaceObject("Eris", 1170, 7, 16.7, 2.25, 0.662, "Dwarf planet"),
                new SpaceObject("Pluto", 1153, 7.15, 13.105, 2.0, 0.61, "Dwarf planet"),
                new SpaceObject("Makemake", 710, 1.8, 3, 2.0, 0.4, "Dwarf planet"),
                new SpaceObject("Haumea", 575, 1.3, 4.006, 3, 0.44, "Dwarf planet"),
                new SpaceObject("Ceres", 475, 0.437, 0.95, 2.08, 0.27, "Dwarf planet"),
                new SpaceObject("Pallas", 266, 0.078, 0.211, 2.8, 0.2, "Asteroid"),
                new SpaceObject("Vesta", 264.6, 0.078, 0.262, 3.42, 0.251, "Asteroid")
            })
        };
    }
}
csharp
// ...
builder.Services.AddSingleton<SpaceObjectDataProvider>();

Display/Hide Exported Columns

The TreeList exports data of all data columns unless you assign false to a column’s ExportEnabled property. A column whose Visible property is set to false is exported as a hidden column (has a zero width).

Handle the CustomizeColumn event and specify the Column.IsHidden argument to display/hide columns in the output document:

csharp
async Task ExportXlsx_Click() {
    await TreeList.ExportToXlsxAsync("ExportResult", new TreeListXlExportOptions() {
        CustomizeColumn = CustomizeColumn,
    });
}
void CustomizeColumn(TreeListExportCustomizeColumnEventArgs e) {
    // Shows every TreeList column in the output document
    e.Column.IsHidden = false;
}

Specify Column Width

Use the ExportWidth property to specify the column width in the exported document:

razor
@inject SpaceObjectDataProvider SpaceObjectDataProvider

<DxButton Text="Export to XLSX" Click="ExportXlsx_Click" />
<DxTreeList @ref="TreeList" Data="TreeListData" ChildrenFieldName="Satellites">
    <Columns>
        <DxTreeListDataColumn FieldName="Name" ExportWidth="150" />
        <DxTreeListDataColumn FieldName="TypeOfObject" Caption="Type" ExportWidth="100"/>
        <DxTreeListDataColumn FieldName="Mass10pow21kg" Caption="Mass, kg" DisplayFormat="N2">
            <HeaderCaptionTemplate>Mass, 10<sup>21</sup> &#215; kg</HeaderCaptionTemplate>
        </DxTreeListDataColumn>
        <DxTreeListDataColumn FieldName="MeanRadiusInKM" Caption="Radius, km" DisplayFormat="N2" />
        <DxTreeListDataColumn FieldName="Volume10pow9KM3" Caption="Volume, km³" DisplayFormat="N2" />
        <DxTreeListDataColumn FieldName="SurfaceGravity" DisplayFormat="N2" />
    </Columns>
</DxTreeList>

@code {
    ITreeList TreeList { get; set; }
    object TreeListData { get; set; }

    protected override async Task OnInitializedAsync() {
        TreeListData = SpaceObjectDataProvider.GenerateData();
    }
    async Task ExportXlsx_Click() {
        await TreeList.ExportToXlsxAsync("ExportResult");
    }
}

Note that Microsoft Excel performs width calculation in characters. When you open a document, Excel converts the column width in pixels to characters. The column width in characters differs on a machine with more than 100% DPI - the resulting width in pixels differs from the specified value. You can handle the CustomizeColumn action and specify the Column.WidthInCharacters property to set the column width in characters.

csharp
async Task ExportXlsx_Click() {
    await TreeList.ExportToXlsxAsync("ExportResult", new TreeListXlExportOptions() {
        CustomizeColumn = CustomizeColumn,
    });
}
void CustomizeColumn(TreeListExportCustomizeColumnEventArgs e) {
    if (e.FieldName == "TypeOfObject" || e.FieldName == "Name")
        e.Column.WidthInCharacters = 13;
}

Hide Column Headers

Set the ExportColumnHeaders property to false to exclude the column header row from export:

csharp
async Task ExportXlsx_Click() {
    await TreeList.ExportToXlsxAsync("ExportResult", new TreeListXlExportOptions() {
        ExportColumnHeaders = false,
    });
}

Handle the CustomizeSheet event and use its Sheet.PrintTitles argument to repeat specific rows and columns on every printed page:

csharp
async Task ExportXlsx_Click() {
    await TreeList.ExportToXlsxAsync("ExportResult", new TreeListXlExportOptions() {
        CustomizeSheet = CustomizeSheet
    });
}
void CustomizeSheet(TreeListExportCustomizeSheetEventArgs e) {
    // Prints the first row on every page.
    e.Sheet.PrintTitles.SetRows(0, 0);
}

Expand/Collapse Rows

The TreeList preserves row expanded state during export. Use the RowExpandMode property to expand/collapse all rows in the exported document:

csharp
async Task ExportXlsx_Click() {
    await TreeList.ExportToXlsxAsync("ExportResult", new TreeListXlExportOptions() {
        RowExpandMode = TreeListExportRowExpandMode.ExpandAll,
    });
}

To export all rows as a plain list, set the RowExpandMode property to None.

Export Selected Rows

Assign true to the ExportSelectedRowsOnly property to export only selected rows:

csharp
async Task ExportXlsx_Click() {
    await TreeList.ExportToXlsxAsync("ExportResult", new TreeListXlExportOptions() {
        ExportSelectedRowsOnly = true,
    });
}

Once enabled, the TreeList component ignores hierarchy and exports selected records as flat data. Set SelectedRowsExportMode to KeepHierarchy to export selected rows and their parents:

csharp
async Task ExportXlsx_Click() {
    await TreeList.ExportToXlsxAsync("ExportResult", new TreeListXlExportOptions() {
        ExportSelectedRowsOnly = true,
        SelectedRowsExportMode = TreeListSelectedRowsExportMode.KeepHierarchy
    });
}

Export Display Text

The TreeList component exports cell values. To export display text instead of values, set the ExportDisplayText property to true:

csharp
async Task ExportXlsx_Click() {
    await TreeList.ExportToXlsxAsync("ExportResult", new TreeListXlExportOptions() {
        ExportDisplayText = true,
    });
}

Color Cells

Handle the CustomizeCell event and use the Formatting argument to format exported cells:

csharp
async Task ExportXlsx_Click() {
    await TreeList.ExportToXlsxAsync("ExportResult", new TreeListXlExportOptions() {
        CustomizeCell = CustomizeCell
    });
}
void CustomizeCell(TreeListExportCustomizeCellEventArgs e) {
    // Applies bold formatting to column headers
    if (e.AreaType == DevExpress.Export.SheetAreaType.Header)
        e.Formatting.Font = new XlCellFont() { Bold = true };
    if (e.AreaType == DevExpress.Export.SheetAreaType.DataArea) {
        var spaceObject = (SpaceObject)e.DataItem;
        // Highlights planets
        if (spaceObject.TypeOfObject == "Planet")
            e.Formatting.BackColor = System.Drawing.Color.LightBlue;
    }
    // Applies the specified settings.
    e.Handled = true;
}

Add Headers and Footers

Handle CustomizeSheetHeader and CustomizeSheetFooter events to add rows above and below TreeList content in the output document. For additional information, see event descriptions.

Freeze Columns and Rows

Handle the CustomizeSheet event and use its Sheet.SplitPosition argument to freeze rows and columns displayed above and to the left of the specified cell:

csharp
async Task ExportXlsx_Click() {
    await TreeList.ExportToXlsxAsync("ExportResult", new TreeListXlExportOptions() {
        CustomizeSheet = CustomizeSheet
    });
}
void CustomizeSheet(TreeListExportCustomizeSheetEventArgs e) {
    // Freezes the left column and top two rows
    e.Sheet.SplitPosition = new DevExpress.Export.Xl.XlCellPosition(1, 2);
}

Filter Exported Data

Handle the RowExporting event to filter exported data. Set the Cancel event argument to true to exclude the row from the exported document:

csharp
async Task ExportXlsx_Click() {
    await TreeList.ExportToXlsxAsync("Solar System", new TreeListXlExportOptions() {
        RowExporting = RowExporting,
    });
}
void RowExporting(TreeListRowExportingEventArgs args) {
    var spaceObject = (SpaceObject) args.DataItem;
    if (spaceObject.TypeOfObject != "Planet" && spaceObject.TypeOfObject != "Star")
        args.Cancel = true;
}

Specify the Sheet Name

Use the SheetName property to specify the sheet name for the output document:

csharp
async Task ExportXlsx_Click() {
    await TreeList.ExportToXlsxAsync("ExportResult", new TreeListXlExportOptions() {
        SheetName = "Space Objects"
    });
}

Alternatively, you can handle the CustomizeSheet event and use its Sheet.Name argument to customize the sheet name:

csharp
async Task ExportXlsx_Click() {
    await TreeList.ExportToXlsxAsync("ExportResult", new TreeListXlExportOptions() {
        CustomizeSheet = CustomizeSheet
    });
}
void CustomizeSheet(TreeListExportCustomizeSheetEventArgs e) {
    e.Sheet.Name = "Space Objects";
}

Specify Document Print Settings

Handle the CustomizeSheet event and use the Sheet argument to access the following print settings:

PageSetupSpecifies page layout and printing options for a worksheet.PrintOptionsSpecifies options that control how a worksheet is printed.PrintTitlesSpecifies rows and columns to be repeated on every printed page.PrintAreaSpecifies the cell range to be printed.PageMarginsSpecifies page margins used to align the worksheet content on a printed page.

csharp
async Task ExportXlsx_Click() {
    await TreeList.ExportToXlsxAsync("ExportResult", new TreeListXlExportOptions() {
        CustomizeSheet = CustomizeSheet
    });
}
void CustomizeSheet(TreeListExportCustomizeSheetEventArgs e) {
    e.Sheet.PageSetup.PaperKind = DevExpress.Drawing.Printing.DXPaperKind.A4;
    e.Sheet.PageSetup.PageOrientation = DevExpress.Export.Xl.XlPageOrientation.Landscape;
    e.Sheet.PrintTitles.SetColumns(0, 0);
    e.Sheet.PrintTitles.SetRows(0, 0);
    e.Sheet.PageMargins = new DevExpress.Export.Xl.XlPageMargins();
    e.Sheet.PageMargins.PageUnits = DevExpress.Export.Xl.XlPageUnits.Centimeters;
    e.Sheet.PageMargins.Left = 3.0;
    e.Sheet.PageMargins.Right = 3.0;
    e.Sheet.PageMargins.Top = 3.25;
    e.Sheet.PageMargins.Bottom = 3.25;
}

Display Loading Indicators

Use DevExpress Blazor Loading Panel to display a loading indicator during export operations:

razor
@inject SpaceObjectDataProvider SpaceObjectDataProvider

<DxLoadingPanel @bind-Visible="@PanelVisible"
                IsContentBlocked="true"
                ApplyBackgroundShading="true"
                IndicatorAreaVisible="false"
                Text="Exporting Document...">
    <DxButton Text="Export to XLSX" Click="ExportXlsx_Click" />
    <DxTreeList @ref="TreeList" Data="TreeListData" ChildrenFieldName="Satellites">
        <Columns>
            <DxTreeListDataColumn FieldName="Name" />
            <DxTreeListDataColumn FieldName="TypeOfObject" Caption="Type" />
            <DxTreeListDataColumn FieldName="Mass10pow21kg" Caption="Mass, kg" DisplayFormat="N2">
                <HeaderCaptionTemplate>Mass, 10<sup>21</sup> &#215; kg</HeaderCaptionTemplate>
            </DxTreeListDataColumn>
            <DxTreeListDataColumn FieldName="MeanRadiusInKM" Caption="Radius, km" DisplayFormat="N2" />
            <DxTreeListDataColumn FieldName="Volume10pow9KM3" Caption="Volume, km³" DisplayFormat="N2" />
            <DxTreeListDataColumn FieldName="SurfaceGravity" DisplayFormat="N2" />
        </Columns>
    </DxTreeList>
</DxLoadingPanel>

@code {
    ITreeList TreeList { get; set; }
    object TreeListData { get; set; }
    bool PanelVisible { get; set; } = false;

    protected override async Task OnInitializedAsync() {
        TreeListData = SpaceObjectDataProvider.GenerateData();
    }
    async Task ExportXlsx_Click() {
        PanelVisible = true;
        await Task.Yield();
        await TreeList.ExportToXlsxAsync("ExportResult");
        PanelVisible = false;
    }
}

Use the Hyperlink argument of the CustomizeCell event to insert hyperlinks into data cells:

razor
@inject SpaceObjectDataProvider SpaceObjectDataProvider

<DxButton Text="Export to XLSX" Click="ExportXlsx_Click" />
<DxTreeList @ref="TreeList" Data="TreeListData" ChildrenFieldName="Satellites">
    <Columns>
        <DxTreeListDataColumn FieldName="Name" />
        <DxTreeListDataColumn FieldName="TypeOfObject" Caption="Type" />
        <DxTreeListDataColumn FieldName="Mass10pow21kg" Caption="Mass, kg" DisplayFormat="N2" >
            <HeaderCaptionTemplate>Mass, 10<sup>21</sup> &#215; kg</HeaderCaptionTemplate>
        </DxTreeListDataColumn>
        <DxTreeListDataColumn FieldName="MeanRadiusInKM" Caption="Radius, km" DisplayFormat="N2" />
        <DxTreeListDataColumn FieldName="Volume10pow9KM3" Caption="Volume, km³" DisplayFormat="N2" />
        <DxTreeListDataColumn FieldName="SurfaceGravity" DisplayFormat="N2" />
    </Columns>
</DxTreeList>

@code {
    ITreeList TreeList { get; set; }
    object TreeListData { get; set; }

    protected override async Task OnInitializedAsync() {
        TreeListData = SpaceObjectDataProvider.GenerateData();
    }
    async Task ExportXlsx_Click() {
        await TreeList.ExportToXlsxAsync("ExportResult", new TreeListXlExportOptions() {
            CustomizeCell = CustomizeCell
        });
    }
    void CustomizeCell(TreeListExportCustomizeCellEventArgs e) {
        if (e.AreaType == DevExpress.Export.SheetAreaType.DataArea && e.ColumnFieldName == "Name") {
            var spaceObject = e.DataItem as SpaceObject;
            e.Hyperlink = spaceObject.WikiPage;
            e.Handled = true;
        }
    }
}
csharp
using System.Collections.Generic;

public class SpaceObject {
    public string Name { get; set; }
    public double MeanRadiusInKM { get; set; }
    public double Volume10pow9KM3 { get; set; }
    public double Mass10pow21kg { get; set; }
    public double Density { get; set; }
    public double SurfaceGravity { get; set; }
    public string TypeOfObject { get; set; }
    public string WikiPage { get; set; }
    public List<SpaceObject> Satellites { get; set; }
    public SpaceObject(
        string name,
        double meanRadiusInKM,
        double volume10pow9KM3,
        double mass10pow21kg,
        double density,
        double surfaceGravity,
        string typeOfObject,
        string wikiPage,
        List<SpaceObject> satellites = null
    ) {
        Name = name;
        MeanRadiusInKM = meanRadiusInKM;
        Volume10pow9KM3 = volume10pow9KM3;
        Mass10pow21kg = mass10pow21kg;
        Density = density;
        SurfaceGravity = surfaceGravity;
        TypeOfObject = typeOfObject;
        WikiPage = wikiPage;
        Satellites = satellites ?? new List<SpaceObject>();
    }
}
csharp
public class SpaceObjectDataProvider {
    public List<SpaceObject> GenerateData() {
        return new List<SpaceObject>() {
            new SpaceObject("Sun", 696000, 1412000000, 1989100000, 1.409, 274.0, "Star", "https://en.wikipedia.org/wiki/Sun", new List<SpaceObject>() {
                new SpaceObject("Mercury", 2439.7, 60.83, 330.2, 5.43, 3.7, "Planet","https://en.wikipedia.org/wiki/Mercury_(planet)"),
                new SpaceObject("Venus", 6051.8, 928.43, 4868.5, 5.24, 8.872, "Planet", "https://en.wikipedia.org/wiki/Venus"),
                new SpaceObject("Earth", 6371.0, 1083.21, 5973.6, 5.515, 9.78033, "Planet", "https://en.wikipedia.org/wiki/Earth", new List<SpaceObject> () {
                    new SpaceObject("Moon", 1737.1, 21.958, 73.5, 3.3464, 1.625, "Satellite", "https://en.wikipedia.org/wiki/Moon")
                }),
                new SpaceObject("Mars", 3390.0, 163.18, 641.85, 3.94, 3.7, "Planet", "https://en.wikipedia.org/wiki/Mars"),
                new SpaceObject("Jupiter", 69911, 1431280, 1898600, 1.33, 24.79, "Planet", "https://en.wikipedia.org/wiki/Jupiter", new List<SpaceObject>() {
                    new SpaceObject("Ganymede", 2631.2, 76.30, 148.2, 1.936, 1.428, "Satellite", "https://en.wikipedia.org/wiki/Ganymede_(moon)"),
                    new SpaceObject("Callisto", 2410.3, 58.65, 107.6, 1.83, 1.23603, "Satellite", "https://en.wikipedia.org/wiki/Callisto_(moon)"),
                    new SpaceObject("Io", 1821.5, 25.32, 89.3, 3.528, 1.797, "Satellite", "https://en.wikipedia.org/wiki/Io_(moon)"),
                    new SpaceObject("Europa", 1561, 15.93, 48, 3.01, 1.316, "Satellite", "https://en.wikipedia.org/wiki/Europa_(moon)"),
                }),
                new SpaceObject("Saturn", 58232, 827130, 568460, 0.70, 10.445, "Planet", "https://en.wikipedia.org/wiki/Saturn", new List<SpaceObject>() {
                    new SpaceObject("Titan", 2576, 71.52, 134.5, 1.88, 1.354, "Satellite", "https://en.wikipedia.org/wiki/Titan_(moon)"),
                    new SpaceObject("Rhea", 764.4, 1.87, 2.3166, 1.23, 0.26, "Satellite", "https://en.wikipedia.org/wiki/Rhea_(moon)"),
                    new SpaceObject("Iapetus", 736, 1.55, 1.9739, 1.08, 0.223, "Satellite", "https://en.wikipedia.org/wiki/Iapetus_(moon)"),
                    new SpaceObject("Dione", 561.6, 0.73, 1.096, 1.48, 0.232, "Satellite", "https://en.wikipedia.org/wiki/Dione_(moon)"),
                    new SpaceObject("Tethys", 533, 0.624, 0.6173, 1.15, 0.145, "Satellite", "https://en.wikipedia.org/wiki/Tethys_(moon)"),
                    new SpaceObject("Enceladus", 252.1, 0.067, 0.108, 1.61, 0.111, "Satellite", "https://en.wikipedia.org/wiki/Enceladus"),
                    new SpaceObject("Mimas", 198.3, 0.033, 0.03749, 1.15, 0.06363, "Satellite", "https://en.wikipedia.org/wiki/Mimas")
                }),
                new SpaceObject("Uranus", 25362, 68340, 86832, 1.30, 8.87, "Planet", "https://en.wikipedia.org/wiki/Uranus", new List<SpaceObject>() {
                    new SpaceObject("Titania", 788.9, 2.06, 3.526, 1.72, 0.378, "Satellite", "https://en.wikipedia.org/wiki/Titania_(moon)"),
                    new SpaceObject("Oberon", 761.4, 1.85, 3.014, 1.63, 0.347, "Satellite", "https://en.wikipedia.org/wiki/Oberon_(moon)"),
                    new SpaceObject("Umbriel", 584.7, 0.84, 1.2, 1.4, 0.234, "Satellite", "https://en.wikipedia.org/wiki/Umbriel"),
                    new SpaceObject("Ariel", 578.9, 0.81, 1.35, 1.67, 0.269, "Satellite", "https://en.wikipedia.org/wiki/Ariel_(moon)"),
                    new SpaceObject("Miranda", 235.8, 0.055, 0.0659, 1.20, 0.07910375, "Satellite", "https://en.wikipedia.org/wiki/Miranda_(moon)"),
                }),
                new SpaceObject("Neptune", 24622, 62540, 102430, 1.76, 11.15, "Planet", "https://en.wikipedia.org/wiki/Neptune", new List<SpaceObject>() {
                    new SpaceObject("Triton", 1353.4, 10.38, 21.5, 2.061, 0.782, "Satellite", "https://en.wikipedia.org/wiki/Triton_(moon)"),
                    new SpaceObject("Proteus", 210, 0.038, 0.050, 1.3, 0.0666, "Satellite", "https://en.wikipedia.org/wiki/Proteus_(moon)"),
                }),
                new SpaceObject("Eris", 1170, 7, 16.7, 2.25, 0.662, "Dwarf planet", "https://en.wikipedia.org/wiki/Eris_(dwarf_planet)"),
                new SpaceObject("Pluto", 1153, 7.15, 13.105, 2.0, 0.61, "Dwarf planet", "https://en.wikipedia.org/wiki/Pluto"),
                new SpaceObject("Makemake", 710, 1.8, 3, 2.0, 0.4, "Dwarf planet", "https://en.wikipedia.org/wiki/Makemake"),
                new SpaceObject("Haumea", 575, 1.3, 4.006, 3, 0.44, "Dwarf planet", "https://en.wikipedia.org/wiki/Haumea"),
                new SpaceObject("Ceres", 475, 0.437, 0.95, 2.08, 0.27, "Dwarf planet", "https://en.wikipedia.org/wiki/Ceres_(dwarf_planet)"),
                new SpaceObject("Pallas", 266, 0.078, 0.211, 2.8, 0.2, "Asteroid", "https://en.wikipedia.org/wiki/2_Pallas"),
                new SpaceObject("Vesta", 264.6, 0.078, 0.262, 3.42, 0.251, "Asteroid", "https://en.wikipedia.org/wiki/4_Vesta")
            })
        };
    }
}
csharp
// ...
builder.Services.AddSingleton<SpaceObjectDataProvider>();