Skip to content
CanopyX

Data grid

Typed sorting and filters, facets, grouping with aggregates, pinned columns, saved views, editing and export.

CanopyDataGridView1,200 devices in one HTML pageDocumentation for the data grid

18 demos

Device inventory Open this demo full screen

Typed sorting and filters, facets, grouping with aggregates, pinned columns, saved views, editing and export.

Build one like it

The smallest complete version, in each language CanopyX supports for this view. The demo above is the same API with more data.

using CanopyX;
using CanopyX.Html;

var devices = new CanopyDataGridView("devices", "Device inventory") {
    Selection = CanopySelectionMode.Multiple,
    StatusBar = true,
    Noun = "devices",
    Reporting = new CanopyGridReporting {
        Grouping = new CanopyGridGrouping("site"),
        HeaderFilters = true
    }
};
devices.Columns.Add(new CanopyColumn("device", "Device") {
    Sortable = true,
    Presenter = CanopyGridPresenter.Identifier(mono: true)
});
devices.Columns.Add(new CanopyColumn("site", "Site") { Sortable = true });
devices.Columns.Add(new CanopyColumn("os", "Operating system") { Sortable = true });
devices.Columns.Add(new CanopyColumn("patch", "Patch level") {
    Kind = CanopyColumnKind.Number,
    Sortable = true,
    Presenter = CanopyGridPresenter.Progress()
});
devices.Columns.Add(new CanopyColumn("encrypted", "Encrypted") {
    Sortable = true,
    Presenter = CanopyGridPresenter.Boolean()
});
devices.Reporting.FacetColumns.Add("site");
devices.Reporting.FacetColumns.Add("os");
devices.Reporting.Aggregates.Add(new CanopyGridAggregate(
    "patch-average", "patch", CanopyGridAggregateOperation.Average,
    "Average patch level"));

foreach (var (name, site, os, patch, encrypted) in new[] {
    ("WS-WAW-0001", "Warsaw", "Windows 11 24H2", 96, true),
    ("WS-WAW-0002", "Warsaw", "Windows 10 22H2", 61, false),
    ("SRV-WAW-0003", "Warsaw", "Windows Server 2025", 88, true),
    ("WS-LON-0004", "London", "Windows 11 24H2", 100, true),
    ("WS-LON-0005", "London", "Windows 11 23H2", 74, true),
    ("SRV-BER-0006", "Berlin", "Windows Server 2022", 58, true)
}) {
    var row = new CanopyGridRow(name.ToLowerInvariant());
    row.Cells["device"] = name;
    row.Cells["site"] = site;
    row.Cells["os"] = os;
    row.Cells["patch"] = new CanopyCell(patch) {
        Text = $"{patch}%",
        Tone = patch < 70 ? CanopyTone.Danger : CanopyTone.None
    };
    row.Cells["encrypted"] = encrypted;
    devices.Rows.Add(row);
}
devices.SaveHtmlPage("inventory.html");

Run this snippet (data grid, C#)Its output, generated with the site.

Try this in the demo

  1. Grouping

    Collapse the Berlin group heading.

    The heading keeps its count and its patch level summary; collapsed rows still count in selections and exports.

  2. Facets

    Open the filter in the Site or Operating system header and tick a few values.

    The value counts come from all 1,200 devices that match, not from the rows on screen.

  3. Aggregates

    Read the totals row under the grid, then filter.

    Average and lowest patch level follow the filtered query.

  4. Selection

    Tick a few rows, then use Select all matching.

    The status bar counts the selection. Select all matching captures the query instead of every record ID.

  5. CSV export

    Open Export and choose Download CSV.

    Pick filtered, selected or all records. The file follows the accepted query and the column order, not the visible rows.

  6. Saved views

    Hide a column, then open Views and save the layout.

    Named views keep columns, filters and sorting, and Reset view returns to the definition.