Bar Chart

Grouped and stacked bars with sub-cell precision, axes, and legend.

Overview

The BarChart control renders one or more ChartSeries as categorical bars. Series can be laid out grouped (side by side) or stacked, in either vertical or horizontal orientation. Bar lengths use Unicode eighth-blocks for smooth sub-cell resolution, and a "nice-number" value axis, dotted grid, category labels, and a legend are drawn automatically. Provide data inline with <ChartSeries>/<ChartDataPoint> elements, or bind a collection to SeriesSource.

<BarChart Title="Quarterly revenue" BarMode="Grouped">
    <ChartSeries Name="2024">
        <ChartDataPoint Label="Q1" Value="42" />
        <ChartDataPoint Label="Q2" Value="55" />
        <ChartDataPoint Label="Q3" Value="30" />
        <ChartDataPoint Label="Q4" Value="70" />
    </ChartSeries>
    <ChartSeries Name="2025">
        <ChartDataPoint Label="Q1" Value="35" />
        <ChartDataPoint Label="Q2" Value="60" />
        <ChartDataPoint Label="Q3" Value="48" />
        <ChartDataPoint Label="Q4" Value="90" />
    </ChartSeries>
</BarChart>

<!-- Stacked, horizontal -->
<BarChart BarMode="Stacked" Orientation="Horizontal"> ... </BarChart>

Properties

PropertyTypeDescription
SeriesIList<ChartSeries>Inline series collection (content property).
SeriesSourceIEnumerableBound series collection; overrides Series.
BarModeBarModeGrouped or Stacked.
OrientationOrientationVertical (default) or Horizontal.
ShowValuesboolDraw each bar's numeric value at its tip.
ShowAxes / ShowGrid / ShowLegendboolToggle chart chrome.
SelectedIndexintSelected category index (-1 = none). Two-way bindable.
SelectedItemobjectThe selected category's label, kept in sync with SelectedIndex. Two-way bindable.

Interactivity

The chart is focusable. Give it focus (Tab, or click) and use the arrow keys to move the category selection — ←/→ for vertical bars, ↑/↓ for horizontal — plus Home/End; or click a category directly. The selected category is highlighted (brighter while focused) and SelectedIndex/ SelectedItem update two-way.

Data Binding

Instead of declaring points inline, bind a collection from a ViewModel to SeriesSource. The chart subscribes to INotifyCollectionChanged, so adding or removing a series re-renders automatically. Data classes and ViewModels must be public or internal (never private) so the AOT source generator can emit their binding accessors.

public sealed class RevenueViewModel : ViewModelBase
{
    public ObservableCollection<ChartSeries> Revenue { get; } =
    [
        new ChartSeries { Name = "2024",
            Values = { new() { Label = "Q1", Value = 42 },
                       new() { Label = "Q2", Value = 55 } } },
    ];

    // Adding or removing a whole series re-renders the chart automatically.
    public void AddForecast() => Revenue.Add(new ChartSeries
    {
        Name = "2025",
        Values = { new() { Label = "Q1", Value = 35 },
                   new() { Label = "Q2", Value = 60 } }
    });
}
<BarChart SeriesSource="{Binding Revenue}" BarMode="Grouped" />

Note: ChartSeries.Values is a plain list, so mutating points inside an existing series does not auto-refresh — add/remove at the series level, or replace the series, to trigger a redraw.

Key Concepts