Skip to content
CanopyX

Getting started with CanopyX

Install CanopyX, build a file explorer and an inventory table in C#, and render both as script-free tables for email or print.

Install

dotnet add package CanopyX.Html

CanopyX.Html includes the browser assets and brings in CanopyX for the view definitions. Install CanopyX alone when you only need the model, the tree bundle writer or the script-free table renderer.

TargetSupport
.NET 8 and .NET 10Windows, Linux and macOS
.NET Standard 2.0Compatible .NET applications
.NET Framework 4.7.2Windows

Neither .NET package adds third-party runtime dependencies. Generating a report from C# needs no Node.js, npm or JavaScript build step.

Create a file explorer

A CanopyTreeView holds columns and nodes. The first column shows each node's label; the other columns show the node's cells. Numeric values control sorting while Text controls what the reader sees.

Program.csC#
using CanopyX;
using CanopyX.Html;

var files = new CanopyTreeView("files", "Project files");
files.Search = new CanopySearchOptions();
files.Columns.Add(new CanopyColumn("name", "Name") {
    Sortable = true, Sizing = CanopyColumnSizing.Preferred(250)
});
files.Columns.Add(new CanopyColumn("size", "Size") {
    Kind = CanopyColumnKind.Number, Sortable = true
});
files.Columns.Add(new CanopyColumn("owner", "Owner") { Sortable = true });

var projects = new CanopyNode("projects", "Projects") { Expanded = true };
projects.Children.Add(File("plan", "Project plan.docx", 48_128, "anna.kowalska"));
projects.Children.Add(File("budget", "Budget 2026.xlsx", 22_016, "ben.okafor"));
var report = File("report", "Quarterly report.pdf", 2_048, "chen.wei");
report.Badges.Add(new CanopyBadge("new", CanopyTone.Info));
projects.Children.Add(report);

var archive = new CanopyNode("archive", "Archive");
archive.Children.Add(File("plan-2025", "Plan 2025.docx", 40_960, "anna.kowalska"));
archive.Children.Add(File("budget-2025", "Budget 2025.xlsx", 19_456, "ben.okafor"));

files.Roots.Add(projects);
files.Roots.Add(archive);

CanopyNode File(string id, string name, long bytes, string owner) {
    var node = new CanopyNode(id, name);
    node.Cells["size"] = new CanopyCell(bytes) { Text = $"{bytes / 1024} KiB" };
    node.Cells["owner"] = owner;
    return node;
}

files.SaveHtmlPage("files.html");
Outputfiles.html7 nodes, tree runtimeOpen files.html in its own page
The page this code writes, running here. Expand Archive, sort by Size or Owner, or search for budget.

For a larger tree, write a bundle that loads branches on demand with files.SaveHtmlBundle("file-report"). Delivery modes shows the files each choice writes.

Keep the bundle together. The generated page, assets and data files belong side by side. The bundle can then be opened directly from disk or a file share.

Create an inventory table

A CanopyDataGridView is a flat list of records. Rows keep their IDs when the reader sorts, so selection and exports refer to the same records whatever the order on screen.

Program.csC#
using CanopyX;
using CanopyX.Html;

var inventory = new CanopyDataGridView("inventory", "Inventory");
inventory.Columns.Add(new CanopyColumn("name", "Name") { Sortable = true });
inventory.Columns.Add(new CanopyColumn("site", "Site") { Sortable = true });
inventory.Columns.Add(new CanopyColumn("size", "Size") {
    Kind = CanopyColumnKind.Number, Sortable = true
});

var records = new[] {
    ("Archive", "Warsaw", 2048L), ("Documents", "London", 512L),
    ("Invoices", "Warsaw", 9216L), ("Photos", "Berlin", 40960L),
    ("Reports", "London", 3072L)
};
foreach (var (name, site, bytes) in records) {
    var row = new CanopyGridRow(name.ToLowerInvariant());
    row.Cells["name"] = name;
    row.Cells["site"] = site;
    row.Cells["size"] = new CanopyCell(bytes) { Text = $"{bytes} bytes" };
    inventory.Rows.Add(row);
}

inventory.SaveHtmlPage("inventory.html");
Outputinventory.html5 rows, grid runtimeOpen inventory.html in its own page
The inventory page, running here. Search the records, sort by any column, and resize or hide columns from the header.

Grouping, facets, aggregates and cell presenters such as progress bars are covered in Reporting grids.

Render a table for email or print

The same two views render as HTML tables with no script and inline styles, ready for an email body, a print layout or a Word document.

Report.csC#
using CanopyX.Rendering;

string treeTable = CanopyStaticHtml.Render(files);
string inventoryTable = CanopyStaticHtml.RenderGrid(inventory);
OutputtreeTable, inventoryTableScript-free HTML, 5.5 KB
Project files
NameSizeOwner
Projects
Project plan.docx47 KiBanna.kowalska
Budget 2026.xlsx21 KiBben.okafor
Quarterly report.pdfnew2 KiBchen.wei
Archive
Plan 2025.docx40 KiBanna.kowalska
Budget 2025.xlsx19 KiBben.okafor
Inventory
NameSiteSize
ArchiveWarsaw2048 bytes
DocumentsLondon512 bytes
InvoicesWarsaw9216 bytes
PhotosBerlin40960 bytes
ReportsLondon3072 bytes
Both strings, exactly as the code returns them. They use literal colours, so mail clients show them the same way; this page shows them on white for that reason.

Email and print covers row limits, the overflow link to the full report, the dark palette and tables that follow the page theme.