| name | devexpress-blazor-gauges |
| description | Generate and configure DevExpress Blazor visualization components such as DxBarGauge, DxRangeSelector, DxSankey, DxSparkline, and DxMap. Use when building dashboards with gauges and range selection, Sankey flow diagrams, sparklines/mini charts, and interactive maps (data binding, labels, palettes, selection/hover/click events). Also use for bar gauge, range selector, Sankey, sparkline, map, and visualization feature comparisons or migration scenarios. |
| compatibility | Requires .NET 8+. NuGet package DevExpress.Blazor is available on NuGet.org. Interactive render mode required for Range Selector selection, Sankey/Map hover and click events. DxMap requires an API key from Azure, Google, or GoogleStatic GIS services. |
| metadata | {"author":"DevExpress","version":"26.1","source-commit":"8493730c9e9a47a009fc307a37c307e157663819"} |
DevExpress Blazor Visualization Components
A collection of specialized visualization components for Blazor:
DxBarGauge — Circular bar gauge displaying multiple values as arcs
DxRangeSelector — Linear scale with draggable sliders for range selection; optionally displays a background chart
DxSankey — Flow diagram showing value transfer between two entity sets
DxSparkline — Compact trend line/bar embedded in other UI (e.g., inside a Grid column)
DxMap — Geo map with markers and route display using Azure, Google, or GoogleStatic tiles
When to Use This Skill
- Display multiple gauge values as concentric arc bars (
DxBarGauge)
- Let users visually select a date/numeric range by dragging sliders (
DxRangeSelector)
- Visualize flow between categories or entities (
DxSankey)
- Embed a compact trend chart inside a Grid cell or card (
DxSparkline)
- Show geo locations, routes, or markers on a map (
DxMap)
- Export gauge/sparkline/sankey as PNG/PDF/JPEG/GIF
Prerequisites & Installation
NuGet Package
| Package | Purpose |
|---|
DevExpress.Blazor | All components in this skill |
dotnet add package DevExpress.Blazor
Register in Program.cs:
builder.Services.AddDevExpressBlazor();
v26.1 note: DevExpress.Blazor no longer includes options.BootstrapVersion or DevExpress.Blazor.BootstrapVersion. Do not generate either API.
Add to _Imports.razor:
@using DevExpress.Blazor
Apply a theme and add client scripts in App.razor inside <head>:
@using DevExpress.Blazor
@DxResourceManager.RegisterTheme(Themes.Fluent)
@DxResourceManager.RegisterScripts()
DxMap requires a GIS API key (Azure Maps, Google Maps, or GoogleStatic). Pass it via the DxMapApiKeys child component and set Provider.
Before You Start — Ask the Developer
Before generating code, ask:
- Render mode:
InteractiveServer, InteractiveWebAssembly, InteractiveAuto, or Static/SSR? (Range Selector dragging and Map/Sankey click events require interactivity)
- Which component?: Bar Gauge, Range Selector, Sankey, Sparkline, or Map?
- Data source: Collection type and field names (for Sankey: source, target, weight fields; for Sparkline: argument, value fields)
- For Bar Gauge: How many values? What is the scale range (
StartValue/EndValue)?
- For Range Selector: Numeric or DateTime scale? Does the user need a background chart?
Does the selected range need to filter or drive other components?
(If yes → use ValueChanged event with RangeSelectorValueChangedEventArgs; never use @bind-SelectedRangeStartValue.)
- For Map: Which GIS provider? Do you have an API key?
Component Overview
DxBarGauge — Quick Pattern
@rendermode InteractiveServer
<DxBarGauge Width="100%"
Height="400px"
StartValue="0"
EndValue="100"
Values="@Values">
<DxBarGaugeLabelSettings Indent="30" />
<DxBarGaugeLegendSettings Visible="true"
ItemCaptions="@Captions"
VerticalAlignment="VerticalEdge.Bottom"
HorizontalAlignment="HorizontalAlignment.Center" />
</DxBarGauge>
@code {
double[] Values = new double[] { 47.27, 65.32, 84.59 };
string[] Captions = new string[] { "Metacritic", "Rotten Tomatoes", "IMDb" };
}
DxSankey — Quick Pattern
<DxSankey Data="@Data"
Width="100%"
Height="440px"
SourceFieldName="Source"
TargetFieldName="Target"
WeightFieldName="Weight">
<DxSankeyNodeSettings Width="8" Spacing="30" />
<DxSankeyLinkSettings ColorMode="SankeyLinkColorMode.Gradient" />
<DxTitleSettings Text="Commodity Turnover" />
</DxSankey>
DxSparkline — Quick Pattern
<DxSparkline Data="@DataSource"
Type="SparklineType.Bar"
ArgumentFieldName="Month"
ValueFieldName="VisitorCount"
Height="50px"
Width="200px" />
DxRangeSelector — Quick Pattern
<DxRangeSelector Data="@Data">
<DxRangeSelectorScale StartValue="@(new DateTime(2024, 1, 1))"
EndValue="@(new DateTime(2024, 12, 31))"
TickInterval="ChartAxisInterval.Month"
ValueType="ChartAxisDataType.DateTime" />
<DxRangeSelectorChart>
<DxChartBarSeries ArgumentField="@((DataPoint s) => s.Date)"
ValueField="@((DataPoint s) => s.Value)" />
</DxRangeSelectorChart>
</DxRangeSelector>
DxMap — Quick Pattern
@rendermode InteractiveServer
<DxMap Provider="MapProvider.Azure"
Zoom="12"
Width="950px"
Height="500px">
<DxMapApiKeys Azure="YOUR-AZURE-MAPS-KEY" />
<DxMapMarkers>
<DxMapMarker>
<DxMapMarkerLocation Latitude="51.5074" Longitude="-0.1278" />
<DxMapMarkerTooltip Text="London" />
</DxMapMarker>
</DxMapMarkers>
</DxMap>
Note: DxMap requires a GIS provider API key. Use MapProvider.GoogleStatic for a quick static-image test without interactive tile setup.
Documentation & Navigation Guide
Bar Gauge
📄 references/bar-gauge.md
When you need to: configure gauge geometry (start/end values, base value), labels, legend, tooltips, palette, or export.
Range Selector
📄 references/range-selector.md
When you need to: configure scale (type, tick intervals, min/max range), set a predefined selected range, display a background chart, or handle selection change events.
Sankey
📄 references/sankey.md
When you need to: bind Sankey to data (source/target/weight fields), configure nodes/links/labels, handle click/hover events, or customize appearance.
Sparkline
📄 references/sparkline.md
When you need to: embed a sparkline in a Grid column, choose series type, configure min/max highlighting, win/loss display, or export.
Map
📄 references/map.md
When you need to: display markers or routes on a geo map, set the GIS provider (Azure, Google, or GoogleStatic), configure the API key, handle marker click events, or customize map zoom and center.
Getting Started (All Components)
📄 references/getting-started.md
When you need to: install and configure the NuGet package, add CSS/imports, or set up the first component.
Key Properties & API Surface
DxBarGauge
| Property | Type | Description |
|---|
Values | double[] | Array of values to display as gauge arcs |
StartValue | double | Minimum scale value |
EndValue | double | Maximum scale value |
BaseValue | double | Base value for bars (bars grow from this value) |
Width / Height | string | Component dimensions |
Palette | string[] | Colors for each bar |
ExportAsync() | Task<string> | Export as base64 image |
DxSankey
| Property | Type | Description |
|---|
Data | IEnumerable<T> | Data source |
SourceFieldName | string | Field name for the flow source node |
TargetFieldName | string | Field name for the flow target node |
WeightFieldName | string | Field name for the flow weight/volume |
Width / Height | string | Component dimensions |
DxSparkline
| Property | Type | Description |
|---|
Data | IEnumerable<T> | Data source |
ArgumentFieldName | string | Field name for argument values |
ValueFieldName | string | Field name for data values |
Type | SparklineType | Series type: Line, Bar, Spline, SplineArea, Area, StepLine, StepArea, WinLoss |
Width / Height | string | Component dimensions |
DxRangeSelector
| Property | Type | Description |
|---|
Data | IEnumerable<T> | Optional data source for background chart |
SelectedRangeStartValue | object | Initial start of the selected range |
SelectedRangeEndValue | object | Initial end of the selected range |
SelectedRangeLength | ChartAxisInterval | Length of initial selected range |
ValueChanged | EventCallback<RangeSelectorValueChangedEventArgs> | Fires when the selected range changes. args.CurrentRange is a List<object> with two items — use .Count (not .Length) to check availability. For DateTime ranges cast defensively: args.CurrentRange.FirstOrDefault() as DateTime? ?? fallback. For numeric ranges use Convert.ToInt32(args.CurrentRange.FirstOrDefault() ?? fallback). |
ValueChangeMode | RangeSelectorValueChangeMode | When to raise ValueChanged: OnHandleMove (live) or OnHandleRelease (on drop). Default: OnHandleRelease. |
DxMap
| Property | Type | Description |
|---|
Provider | MapProvider | GIS provider: Azure, Google, GoogleStatic |
Zoom | int | Map zoom level |
DxMapApiKeys | child component | Supplies the API key; set Azure, Google, or GoogleStatic attribute to the appropriate key |
Markers | collection | Markers to display on the map |
Routes | collection | Routes to display on the map |
Common Patterns
Pattern 1: Bar Gauge with Labels and Legend
<DxBarGauge Width="100%"
Height="500px"
StartValue="0"
EndValue="100"
Values="@Values">
<DxBarGaugeLabelSettings Indent="30"
ConnectorColor="purple"
ConnectorWidth="4">
<DxFontSettings Weight="600" />
<DxTextFormatSettings LdmlString="@LabelFormat" />
</DxBarGaugeLabelSettings>
<DxBarGaugeLegendSettings Visible="true"
ItemCaptions="@LegendItemCaptions"
VerticalAlignment="VerticalEdge.Bottom"
HorizontalAlignment="HorizontalAlignment.Center" />
</DxBarGauge>
@code {
double[] Values = new double[] { 47.27, 65.32, 84.59, 81.86, 99 };
string[] LegendItemCaptions = new string[] { "Metacritic", "Ratingraph.com", "Rotten Tomatoes", "IMDb", "TV.com" };
string LabelFormat = "##.#'%' ";
}
Pattern 2: Sankey with Gradient Links
<DxSankey Data="@Data"
Width="100%"
Height="440px"
SourceFieldName="Source"
TargetFieldName="Target"
WeightFieldName="Weight">
<DxSankeyNodeSettings Width="8" Spacing="30" />
<DxSankeyLinkSettings ColorMode="SankeyLinkColorMode.Gradient" />
<DxTitleSettings Text="Commodity Turnover" />
</DxSankey>
@code {
IEnumerable<SankeyDataPoint> Data = Enumerable.Empty<SankeyDataPoint>();
protected override void OnInitialized() {
Data = new List<SankeyDataPoint> {
new SankeyDataPoint("Spain", "United States of America", 2),
new SankeyDataPoint("Germany", "United States of America", 8),
new SankeyDataPoint("France", "Great Britain", 4),
};
}
record SankeyDataPoint(string Source, string Target, int Weight);
}
Pattern 3: Range Selector with DateTime Scale
<DxRangeSelector Width="1100px"
Height="200px"
SelectedRangeStartValue="@(new DateTime(2024, 2, 1))"
SelectedRangeEndValue="@(new DateTime(2024, 2, 14))">
<DxRangeSelectorScale StartValue="@(new DateTime(2024, 1, 1))"
EndValue="@(new DateTime(2024, 6, 1))"
TickInterval="ChartAxisInterval.Week"
MinorTickInterval="ChartAxisInterval.Day"
MinRange="ChartAxisInterval.Week"
MaxRange="ChartAxisInterval.Month"
ValueType="ChartAxisDataType.DateTime" />
</DxRangeSelector>
Pattern 4: Range Selector Filtering a Chart
Critical: DxRangeSelector does NOT expose SelectedRangeStartValueChanged or SelectedRangeEndValueChanged.
Do not use @bind-SelectedRangeStartValue — it silently does nothing.
Always use the ValueChanged event to react to slider movement.
CurrentRange runtime shape: RangeSelectorValueChangedEventArgs.CurrentRange is a List<object>, not an array. Use .Count (not .Length) to guard against an empty collection. Access the start value with .FirstOrDefault() and the end value with .LastOrDefault(), then cast each item defensively to the target type.
@rendermode InteractiveServer
<DxRangeSelector Data="@AllData"
SelectedRangeStartValue="@RangeStart"
SelectedRangeEndValue="@RangeEnd"
ValueChanged="@OnRangeChanged"
ValueChangeMode="RangeSelectorValueChangeMode.OnHandleMove"
Width="100%" Height="150px">
<DxRangeSelectorScale StartValue="@(new DateTime(2024, 1, 1))"
EndValue="@(new DateTime(2024, 12, 31))"
TickInterval="ChartAxisInterval.Month"
ValueType="ChartAxisDataType.DateTime" />
<DxRangeSelectorChart>
<DxChartBarSeries ArgumentField="@((DataPoint s) => s.Date)"
ValueField="@((DataPoint s) => s.Value)" />
</DxRangeSelectorChart>
</DxRangeSelector>
<DxChart Data="@FilteredData" Width="100%" Height="400px">
<DxChartBarSeries ArgumentField="@((DataPoint s) => s.Date)"
ValueField="@((DataPoint s) => s.Value)"
Name="Value" />
</DxChart>
@code {
DateTime RangeStart = new DateTime(2024, 1, 1);
DateTime RangeEnd = new DateTime(2024, 12, 31);
IEnumerable<DataPoint> AllData = Enumerable.Empty<DataPoint>();
IEnumerable<DataPoint> FilteredData = Enumerable.Empty<DataPoint>();
protected override void OnInitialized() {
AllData = GenerateData();
ApplyFilter();
}
void OnRangeChanged(RangeSelectorValueChangedEventArgs args) {
RangeStart = args.CurrentRange.FirstOrDefault() as DateTime? ?? RangeStart;
RangeEnd = args.CurrentRange.LastOrDefault() as DateTime? ?? RangeEnd;
ApplyFilter();
}
void ApplyFilter() =>
FilteredData = AllData.Where(d => d.Date >= RangeStart && d.Date <= RangeEnd);
record DataPoint(DateTime Date, double Value);
}
Pattern 5: Range Selector with Numeric Scale Filtering a List
Use a numeric scale (e.g., month indexes 1–12) when your data groups by integer rather than by date. Set ValueType="ChartAxisDataType.Numeric" on the scale. The same CurrentRange-is-List<object> rule applies — use Convert.ToInt32() for defensive numeric casting.
@rendermode InteractiveServer
<DxRangeSelector SelectedRangeStartValue="@StartMonth"
SelectedRangeEndValue="@EndMonth"
ValueChanged="@OnRangeChanged"
ValueChangeMode="RangeSelectorValueChangeMode.OnHandleRelease"
Width="100%" Height="120px">
<DxRangeSelectorScale StartValue="1"
EndValue="12"
ValueType="ChartAxisDataType.Numeric" />
</DxRangeSelector>
<ul>
@foreach (var order in FilteredOrders)
{
<li>@order.Month — @order.Product: @order.Revenue.ToString("C")</li>
}
</ul>
@code {
int StartMonth = 1;
int EndMonth = 12;
List<MonthlyOrder> AllOrders = new()
{
new(1, "Widget A", 4200), new(2, "Widget A", 3800), new(3, "Widget B", 5100),
new(4, "Widget B", 4700), new(5, "Widget A", 5600), new(6, "Widget C", 3200),
new(7, "Widget C", 4100), new(8, "Widget A", 4900), new(9, "Widget B", 5300),
new(10, "Widget C", 4400), new(11, "Widget A", 6100), new(12, "Widget B", 5800),
};
IEnumerable<MonthlyOrder> FilteredOrders = Enumerable.Empty<MonthlyOrder>();
protected override void OnInitialized() => ApplyFilter();
void OnRangeChanged(RangeSelectorValueChangedEventArgs args)
{
if (args.CurrentRange.Count >= 2)
{
StartMonth = Convert.ToInt32(args.CurrentRange.FirstOrDefault() ?? StartMonth);
EndMonth = Convert.ToInt32(args.CurrentRange.LastOrDefault() ?? EndMonth);
}
ApplyFilter();
}
void ApplyFilter() =>
FilteredOrders = AllOrders.Where(o => o.Month >= StartMonth && o.Month <= EndMonth);
record MonthlyOrder(int Month, string Product, decimal Revenue);
}
Troubleshooting
| Symptom | Cause | Solution |
|---|
DxMap shows blank or default tile | Missing or invalid API key | Add <DxMapApiKeys Azure="..." /> (or Google/GoogleStatic) inside <DxMap>; check Provider matches the key |
| Sankey shows no nodes | Wrong field names | Verify SourceFieldName, TargetFieldName, WeightFieldName match actual C# property names (case-sensitive) |
| Bar Gauge shows no bars | Values is empty or null | Initialize Values array with numeric values in OnInitialized |
| Range Selector sliders not moveable | Static render mode | Add @rendermode InteractiveServer (or WASM/Auto) to the page |
| Range Selector slider moves but the chart doesn't update | @bind-SelectedRangeStartValue / @bind-SelectedRangeEndValue used — these properties have no Changed callbacks, so two-way binding is silently ignored | Remove @bind-. Use ValueChanged="@OnRangeChanged" and read args.CurrentRange.FirstOrDefault() / LastOrDefault() for the new DateTime values |
Build fails: 'List<object>' does not contain a definition for 'Length' | CurrentRange is a List<object>, not an array — Length is not defined on List<T> | Replace .Length with .Count. For DateTime ranges cast items with as DateTime? ?? fallback; for numeric ranges use Convert.ToInt32(item ?? fallback) |
| Sparkline not visible in Grid cell | Width/Height not set | Set explicit Width and Height on DxSparkline; use px or % units |
ExportAsync() returns empty | Called too early | Call from OnAfterRenderAsync(firstRender: true) after the component has rendered |
"Unhandled exception on the current circuit" with no detail | CircuitOptions.DetailedErrors not set | Add builder.Services.Configure<CircuitOptions>(o => o.DetailedErrors = true); in Program.cs (development only) |
"Component parameter 'ValueChanged' is used two or more times" compile error | @bind-Value and ValueChanged used together | Use @bind-Value="@val" for two-way binding, or Value="@val" ValueChanged="@handler" — never both simultaneously |
dx-blazor.js not found (404) behind a reverse proxy | Reverse proxy strips the app base path | Add app.UsePathBase("/subpath") before app.MapBlazorHub(), or set <base href="/subpath/" /> in App.razor |
Static assets return 404 (dx-blazor.css, dx-blazor.js) | UseStaticWebAssets() not called | Add app.UseStaticWebAssets(); in Program.cs before app.UseStaticFiles() |
"Could not find 'X' in 'window.DxBlazor'" JavaScript error | Stale browser-cached JS from an older DevExpress version | Hard-refresh the browser (Ctrl+Shift+R), clear site data, or verify all DevExpress NuGet packages are the same version |
"Cannot pass the parameter 'X' to component 'Y' with rendermode" | Non-serializable parameter passed across a render mode boundary | Move the component to a child .razor file with its own @rendermode directive; pass only serializable parameters |
Constraints & Rules
CRITICAL — follow these rules in every interaction:
- Never invent API: If a property, method, event, or feature is not documented in this skill or its references, do not assume it exists. When asked about an unfamiliar API, first try to verify it using the DevExpress documentation MCP (
devexpress_docs_search) or the local apidoc/ folder. Only after checking: if confirmed, use the API; if not found, explicitly state that it does not appear to be part of the DevExpress Blazor component API. Do not warn that a feature "may have been introduced in a recent version" as a way to justify inventing it.
- Build verification: Run
dotnet build after changes. Check for errors before reporting success.
- NuGet packages: Use
DevExpress.Blazor — the exact package listed in Prerequisites.
- Namespace imports: Always include
@using DevExpress.Blazor.
- Version consistency: All DevExpress packages must use the same version.
- License: DevExpress requires a valid license. Remind the developer if they hit license-related build errors.
- Map API key:
DxMap will not display without a valid GIS provider API key. Remind the developer to configure this.
- DxSankey field names:
SourceFieldName, TargetFieldName, WeightFieldName are plain string property names, not lambda expressions.
- DxSparkline field names:
ArgumentFieldName and ValueFieldName are plain string property names.
Using DevExpress Documentation MCP
If the DxDocs MCP server is available, use it to supplement this skill:
- Search:
devexpress_docs_search(technology="Blazor", query="<your question>")
- Fetch:
devexpress_docs_get_content(url="<documentation URL>")
Use MCP for: DxMap route configuration, DxBarGauge palette range configuration, DxRangeSelector background and shutter customization, DxSankey tooltip customization, exact event argument types, or features not covered in the references above.