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.
| Target | Support |
|---|---|
| .NET 8 and .NET 10 | Windows, Linux and macOS |
| .NET Standard 2.0 | Compatible .NET applications |
| .NET Framework 4.7.2 | Windows |
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.
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");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.
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");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.
using CanopyX.Rendering;
string treeTable = CanopyStaticHtml.Render(files);
string inventoryTable = CanopyStaticHtml.RenderGrid(inventory);| Name | Size | Owner |
|---|---|---|
| Projects | ||
| Project plan.docx | 47 KiB | anna.kowalska |
| Budget 2026.xlsx | 21 KiB | ben.okafor |
| Quarterly report.pdfnew | 2 KiB | chen.wei |
| Archive | ||
| Plan 2025.docx | 40 KiB | anna.kowalska |
| Budget 2025.xlsx | 19 KiB | ben.okafor |
| Name | Site | Size |
|---|---|---|
| Archive | Warsaw | 2048 bytes |
| Documents | London | 512 bytes |
| Invoices | Warsaw | 9216 bytes |
| Photos | Berlin | 40960 bytes |
| Reports | London | 3072 bytes |
Email and print covers row limits, the overflow link to the full report, the dark palette and tables that follow the page theme.