Install
$ agentstack add skill-devexpress-agent-skills-devexpress-reports-core ✓ scanned · ✓ verified — works with Claude Code, Cursor, and more.
Security review
✓ PassedNo issues found. Passed automated security review. · v0.1.0 How review works →
- ✓ Prompt-injection patterns
- ✓ Secret / credential exfiltration
- ✓ Dangerous shell & filesystem operations
- ✓ Untrusted network calls
- ✓ Known-malicious package signatures
What it can access
- ✓ Network access No
- ✓ Filesystem access No
- ✓ Shell / process execution No
- ✓ Environment & secrets No
- ✓ Dynamic code execution No
From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.
About
DevExpress XtraReports — Core Runtime API
When to Use This Skill
> CRITICAL — Do not bypass this skill. Whenever this skill is active, follow the patterns and constraints here. Do not substitute your own general knowledge of DevExpress APIs. If a scenario is not covered in the main skill body, read the relevant reference file or use MCP servers before writing code — do not guess API signatures.
Use for any task involving:
- Creating
XtraReportinstances and building report structure in code - Adding bands (DetailBand, GroupHeaderBand, ReportHeaderBand, etc.)
- Adding controls (XRLabel, XRTable, XRChart, XRPictureBox, etc.) to bands
- Binding reports to data sources (IList, DataTable, SqlDataSource, ObjectDataSource)
- Defining report parameters, calculated fields, and expression bindings
- Exporting reports:
ExportToPdf,ExportToXlsx,ExportToDocx,ExportToCsv, etc. - Configuring
PdfExportOptions,XlsxExportOptions, etc. - Saving/loading report layouts with
SaveLayoutToXml/LoadLayoutFromXml - Report types: table, master-detail, cross-tab, label, subreport
> Scope: This skill covers runtime API only — no viewer UI, no print preview, no designer embedding. For platform-specific viewer integration, see: devexpress-reports-aspnetcore, devexpress-reports-blazor, devexpress-reports-winforms, or devexpress-reports-wpf.
Before You Start
Ask the developer:
- Target framework: .NET 6/7/8+ or .NET Framework 4.x?
- Platform: WinForms, WPF, ASP.NET Core, Blazor, console/service, or MAUI?
- Operation: Create a new report in code? Load existing
.repxlayout? Modify an existing report class? - Data source: What data are you binding? (IList/collection, DataTable/DataSet, EF DbContext, SQL database, JSON, Excel, none)
- Output: Export to file/stream? Which format(s)? Or display in a viewer?
- Existing NuGet setup: Are DevExpress packages already installed, or starting fresh?
Prerequisites & Installation
Add the platform NuGet package from nuget.org:
| Platform | NuGet Package | |----------|---------------| | WinForms | DevExpress.Win.Reporting | | WPF | DevExpress.Wpf.Reporting | | ASP.NET Core | DevExpress.AspNetCore.Reporting | | ASP.NET Web Forms and MVC | DevExpress.Web.Reporting | | Console / server | DevExpress.Reporting.Core (core only) |
All packages include the required namespaces (DevExpress.XtraReports.UI, DevExpress.XtraPrinting, DevExpress.Drawing) and export infrastructure.
> Linux/macOS (non-Windows): Add DevExpress.Drawing.Skia for PDF rendering support.
Core Classes Overview
| Class | Namespace | Role | |-------|-----------|------| | XtraReport | DevExpress.XtraReports.UI | Root report object | | DetailBand | DevExpress.XtraReports.UI | Repeating data rows (mandatory) | | ReportHeaderBand | DevExpress.XtraReports.UI | Once at report start | | ReportFooterBand | DevExpress.XtraReports.UI | Once at report end | | GroupHeaderBand | DevExpress.XtraReports.UI | Group header | | GroupFooterBand | DevExpress.XtraReports.UI | Group summary | | PageHeaderBand | DevExpress.XtraReports.UI | Every page top | | PageFooterBand | DevExpress.XtraReports.UI | Every page bottom | | DetailReportBand | DevExpress.XtraReports.UI | Nested (master-detail) data | | XRLabel | DevExpress.XtraReports.UI | Text / field display | | XRTable / XRTableRow / XRTableCell | DevExpress.XtraReports.UI | Tabular layout | | XRPictureBox | DevExpress.XtraReports.UI | Images | | XRChart | DevExpress.XtraReports.UI | Charts | | XRCrossTab | DevExpress.XtraReports.UI | Pivot tables | | XRSubreport | DevExpress.XtraReports.UI | Embedded subreport | | XRPageInfo | DevExpress.XtraReports.UI | Page number, date | | Parameter | DevExpress.XtraReports.Parameters | Report parameter | | CalculatedField | DevExpress.XtraReports.UI | Computed field |
Quick Start — Report in Code
using DevExpress.XtraReports.UI;
var report = new XtraReport {
DataSource = GetProducts(), // IList, DataTable, etc.
Name = "ProductReport"
};
var detail = new DetailBand();
report.Bands.Add(detail);
detail.HeightF = 30;
var nameLabel = new XRLabel();
detail.Controls.Add(nameLabel);
nameLabel.BoundsF = new RectangleF(0, 0, 200, 25);
nameLabel.ExpressionBindings.Add(new ExpressionBinding("BeforePrint", "Text", "[ProductName]"));
// Export
report.ExportToPdf("output.pdf");
See examples/quickstart.cs for a full working example with grouping, a page header, and PDF export.
> Single-field display only: The pattern above uses XRLabel for one field. For reports with multiple side-by-side columns, group subtotals, images, or charts — read references/report-controls.md (control types) and references/report-bands.md (band types) before writing code.
> For designer-backed reports (with InitializeComponent()): do not add a second DetailBand. See Antipatterns (AP7) and Constraint 9.
Export API
All export methods have sync and async variants:
// To file path
report.ExportToPdf("report.pdf");
report.ExportToXlsx("report.xlsx");
report.ExportToDocx("report.docx");
report.ExportToCsv("report.csv");
report.ExportToHtml("report.html");
report.ExportToImage("report.png");
report.ExportToRtf("report.rtf");
report.ExportToText("report.txt");
report.ExportToXls("report.xls");
report.ExportToMht("report.mht");
// To stream (preferred for web/API scenarios)
using var ms = new MemoryStream();
report.ExportToPdf(ms);
// Async (required in web apps)
await report.ExportToPdfAsync(ms);
With options:
var pdfOptions = new DevExpress.XtraPrinting.PdfExportOptions {
PageRange = "1-3",
PdfACompatibility = DevExpress.XtraPrinting.PdfACompatibility.PdfA2b
};
report.ExportToPdf("report.pdf", pdfOptions);
📄 See references/export.md for all ExportOptions classes and their properties.
Common Patterns
Pattern 1 — Data-bound report:
report.DataSource = myList; // IList, DataTable, or DevExpress data source
report.DataMember = "Orders"; // Table name (for DataSet) or empty for simple list
Pattern 2 — Expression binding:
> Do not use DataBindings.Add — this is the legacy binding mode. See Antipatterns (AP1).
// Specify an expression that calculates total value from UnitPrice and UnitsInStock fields.
label.ExpressionBindings.Add(new ExpressionBinding("BeforePrint", "Text", "[UnitPrice]*[UnitsInStock]"));
// Specify an expression that is rendered within the PrintOnPage event.
label.ExpressionBindings.Add(new ExpressionBinding("PrintOnPage", "Text", "'Printed'"));
> Expression function names are NOT .NET method names — see Antipatterns (AP2) and references/expressions.md for the complete catalogue.
Pattern 3 — Report parameter:
// Create a date report parameter.
// Use an expression to specify the parameter's default value.
var dateParameter = new Parameter() {
Name = "date",
Description = "Date:",
Type = typeof(System.DateTime),
ExpressionBindings = { new BasicExpressionBinding("Value", "Now()") }
};
// Add the parameter to the report's Parameters collection.
report.Parameters.Add(dateParameter);
// Create a label and bind the label's Text property to the parameter value.
// Use the parameter's name to reference the parameter in the label's expression.
var dateLabel = new XRLabel();
report.Bands[BandKind.Detail].Controls.Add(dateLabel);
dateLabel.BoundsF = new RectangleF(0, 0, 200, 50);
dateLabel.ExpressionBindings.Add(new ExpressionBinding("BeforePrint", "Text", "?date"));
// Use the parameter in the report filter if needed:
report.FilterString = "[OrderDate] >= ?date";
Pattern 4 — Save/Load layout:
report.SaveLayoutToXml("layout.repx"); // .repx = XML serialization
var loaded = XtraReport.FromXmlFile("layout.repx");
Pattern 5 — CreateDocument before export (optional, ensures data is prepared):
report.CreateDocument(); // sync — OK in desktop apps
// OR in web:
await report.CreateDocumentAsync();
report.ExportToPdf(outputStream);
Pattern 6 — Tabular column layout with XRTable:
> Use XRTable / XRTableRow / XRTableCell for every multi-column layout — data rows, header rows, and summary rows. See Antipatterns (AP3).
var table = new XRTable();
detail.Controls.Add(table);
table.BeginInit();
var row = new XRTableRow();
table.Rows.Add(row);
var nameCell = new XRTableCell { WidthF = 450 }; // absolute column width in pixels
var priceCell = new XRTableCell { WidthF = 200 }; // 450 + 200 = 650 (equals table SizeF.Width)
row.Cells.Add(nameCell);
row.Cells.Add(priceCell);
nameCell.ExpressionBindings.Add(new ExpressionBinding("BeforePrint", "Text", "[ProductName]"));
priceCell.ExpressionBindings.Add(new ExpressionBinding("BeforePrint", "Text", "[UnitPrice]"));
table.SizeF = new SizeF(650, 25); // total width = sum of cell WidthF values
table.EndInit();
// See references/report-controls.md for the full XRTable reference.
Pattern 7 — Group or report summary using XRSummary:
> Summary labels require XRSummary. See Antipatterns (AP5, AP6).
// Pattern A — XRSummary.Func + FormatString (simplest for standard aggregates):
var countLabel = new XRLabel();
groupFooter.Controls.Add(countLabel);
countLabel.BoundsF = new RectangleF(0, 0, 200, 25);
countLabel.Summary = new XRSummary {
Func = SummaryFunc.Count, // .Sum, .Avg, .Max, .Min, .Count, etc.
Running = SummaryRunning.Group, // .Page / .Report
FormatString = "Count: {0}" // {0} is replaced by the calculated value
};
// Pattern B — XRSummary.Running + ExpressionBinding with sum*() for computed expressions:
var totalLabel = new XRLabel();
groupFooter.Controls.Add(totalLabel);
totalLabel.BoundsF = new RectangleF(0, 0, 200, 25);
totalLabel.Summary = new XRSummary { Running = SummaryRunning.Group };
totalLabel.ExpressionBindings.Add(new ExpressionBinding("BeforePrint", "Text", "sumSum([Price])"));
// Other sum*() functions: sumAvg([Field]), sumCount(), sumSum([Field]), sumMin([Field])
// See references/expressions.md for the full Summary Functions reference.
Pattern 8 — Calculate available control width from page dimensions:
// Set Margins first, then compute availableWidth once and reuse it across all bands.
Margins = new DevExpress.Drawing.DXMargins(50, 50, 50, 50); // Left, Right, Top, Bottom
var availableWidth = PageWidthF - Margins.Left - Margins.Right;
// Single control filling the full band width:
label.BoundsF = new RectangleF(0, 0, availableWidth, 25);
table.SizeF = new SizeF(availableWidth, 25);
// Multi-column table — proportional fractions of availableWidth:
cell1.WidthF = availableWidth * 0.67f;
cell2.WidthF = availableWidth * 0.33f;
// Rule: cell1.WidthF + cell2.WidthF must equal table.SizeF.Width exactly.
> Set full-band controls to availableWidth. See Antipatterns (AP9).
Key Properties — XtraReport
| Property | Type | Description | |----------|------|-------------| | DataSource | object | Data source (IList, DataTable, DevExpress source) | | DataMember | string | Table/collection path within the data source | | Bands | BandCollection | All bands in the report | | Parameters | ParameterCollection | Report parameters | | CalculatedFields | CalculatedFieldCollection | Calculated fields | | FilterString | string | Report-level data filter | | ExportOptions | ExportOptions | Default export settings | | StyleSheet | XRControlStyleCollection | Named styles | | ReportUnit | ReportUnit | HundredthsOfAnInch or TenthsOfAMillimeter | | Margins | DXMargins | Page margins (DevExpress.Drawing) | | PaperKind | DXPaperKind | Paper size (DevExpress.Drawing.Printing) | | Landscape | bool | Page orientation |
Troubleshooting
| Symptom | Cause | Fix | |---------|-------|-----| | DetailBand required exception at render | No DetailBand added | Always add a DetailBand to report.Bands | | Export file is empty / 0 bytes | DataSource null or no records | Verify data source returns data before export | | ko is not defined at runtime (web) | Not relevant to core API | See devexpress-reports-aspnetcore skill | | PDF export fails on Linux | Missing Skia package | Add DevExpress.Drawing.Skia NuGet package | | ExpressionBinding has no effect | Binding added to wrong property name | Check property name is "Text", "Visible", etc. — case-sensitive | | LoadLayoutFromXml loses data source | .repx does not store data | Re-assign DataSource after LoadLayoutFromXml | | Build error: namespace not found | Missing using directive | Add using DevExpress.XtraReports.UI; and using DevExpress.XtraReports.Parameters; | | CreateDocument() hangs in web app | Blocking call on async context | Use await report.CreateDocumentAsync() in web/API | | Code uses DataBindings.Add("Text", null, "Field") | Legacy binding API | Replace with ExpressionBindings.Add(new ExpressionBinding("BeforePrint", "Text", "[Field]")). See Constraint 13. | | Group footer label shows last value, or error XRE093 "no summary functions" | Expression uses Sum([Field]) — not a valid DevExpress reporting function | Replace with sumSum([Field]); ensure label.Summary.Running is set. See Pattern 7 and references/expressions.md | | Summary label displays expression literally or shows 0 / nothing | XRSummary not set on the label — sumCount(), sumSum() etc. were used in ExpressionBinding without label.Summary | Assign label.Summary = new XRSummary { Running = SummaryRunning.Group } (Pattern A or B). XRSummary is always required. See Pattern 7. | | Expression binding silently ignored or runtime error with unrecognized function | Expression function name guessed from C# knowledge (e.g., Format(), String.Format(), ToString()) — no such function in DevExpress expression language | Use FormatString(format, value) for formatting; check references/expressions.md for the full function list. See Pattern 2. | | System.Exception: Incorrect band type at report constructor | A second instance of a singleton band (DetailBand, TopMarginBand, BottomMarginBand) was added via Bands.Add() after the singleton band was already created previously | Remove the Bands.Add() call; get the existing band from the designer field (e.g., detailBand1) and configure it directly. See Constraint 9. |
Constraints & Rules
- Always add DetailBand for newly created reports:
XtraReportrequires at least oneDetailBandinBandsto render. - Never mix package versions: All DevExpress NuGet packages in a project must be the same version (e.g., all
26.1.*). - Namespace imports: Always include
using DevExpress.XtraReports.UI;. Never assume it exists. - ExpressionBinding property names are case-sensitive:
"Text"not"text". - DataSource is not serialized:
.repxfiles store layout only. When loading withLoadLayoutFromXml, re-assignDataSourceexplicitly. When usingXtraReport.FromXmlStream(), the concrete subclass is restored so constructor-assigned data sources are preserved — but any runtime-assigned data must still be re-assigned. - Async in web: Use
await report.CreateDocumentAsync()andawait report.ExportToPdfAsync()in ASP.NET Core and Blazor. - No destructive changes: When modifying existing report classes, preserve existing band/control structure; only add or modify what is required.
- Verify build: Always run
dotnet buildand confirm 0 errors before reporting task complete. - Singleton bands in designer-backed reports:
XtraReportenforces exactly oneDetailBand, oneTopMarginBand, and oneBottomMarginBand. In a designer-backed partial class (one withInitializeComponent()), these bands already exist.
…
Source & license
This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.
- Author: DevExpress
- Source: DevExpress/agent-skills
- License: MIT
- Homepage: https://www.devexpress.com
Install and usage instructions live in the source repository linked above.
Reviews
No reviews yet — be the first.
Write a review
Versions
- v0.1.0 Imported from the upstream source.