Bar Chart

Render a bar chart by setting Type="bar" on the FluentUIChart component. Pass a list of category labels and one or more ChartDataset objects to define the bars. FluentUIChart is a theme-aware wrapper around the underlying Chart component, which is built on top of Chart.js.

<FluentUIChart Type="ChartType.Bar"
               Labels="_labels"
               Datasets="_datasets" />

@code {
    private List<string> _labels = new() { "Jan", "Feb", "Mar" };

    private List<ChartDataset> _datasets = new()
    {
        new ChartDataset
        {
            Label = "Sales",
            Data = new List<IDataPoint>
            {
                new DataPoint(65), new DataPoint(59), new DataPoint(80),
            },
        },
        new ChartDataset
        {
            Label = "Returns",
            Data = new List<IDataPoint>
            {
                new DataPoint(12), new DataPoint(19), new DataPoint(8),
            },
        },
    };
}

Theme Awareness

Chart.js renders to an HTML <canvas>, so CSS cannot reach into bars, axis labels, or gridlines — they are rasterized pixels. FluentUIChart works around this by reading the resolved CSS custom properties at render time and pushing the values into the Chart.js options as color, scale.ticks.color, and scale.grid.color. It subscribes to ThemeService.ThemeChanged and reapplies the palette whenever the theme changes.

Automatic Dataset Colors

Datasets that leave BackgroundColor or BorderColor null are auto-filled from a Fluent-derived series palette starting with the current accent color. Datasets that supply explicit colors are passed through unchanged.

Element Click Handling

Subscribe to OnElementClick to be notified when the user clicks on a bar (or any rendered element). The callback receives a ChartClickEventArgs with the dataset index, data index, label, value, dataset label, and the original IDataPoint instance. Subclass DataPoint to attach caller-defined context (record id, region, category, etc.) and pattern-match against your subclass in the click handler to recover it. Clicks on the chart background are ignored.

<FluentUIChart Type="ChartType.Bar"
               Labels="_labels"
               Datasets="_datasets"
               OnElementClick="OnBarClicked" />

@code {
    private class SalesDataPoint : DataPoint
    {
        public SalesDataPoint(double value) : base(value) { }
        public string Region { get; set; } = string.Empty;
    }

    private void OnBarClicked(ChartClickEventArgs args)
    {
        // Pattern-match args.DataPoint to recover any caller-defined context.
        if (args.DataPoint is SalesDataPoint sdp)
        {
            Console.WriteLine($"{args.Label}: {sdp.Value} ({sdp.Region})");
        }
    }
}

Chart Title

Set Title to display a heading above the chart. The title is rendered by Chart.js inside the canvas and uses the current theme's text color.

<DataverseChart Source="_source"
                Type="ChartType.Bar"
                Title="Revenue by Year" />

Stacked Charts

Set Stacked="true" to stack datasets on top of each other rather than side-by-side. This is useful for bar and line charts with multiple series where the total across all series is meaningful (e.g. total revenue = won + lost).

<DataverseChart Source="_source"
                Type="ChartType.Bar"
                Stacked="true" />

Legend Position

Set LegendPosition to control where the legend appears: "top" (default), "bottom", "left", "right", or "hidden" to hide it entirely.

<!-- Position: Top (default), Bottom, Left, Right -->
<DataverseChart Source="_source"
                LegendPosition="ChartLegendPosition.Bottom" />

<!-- Hide the legend entirely -->
<DataverseChart Source="_source"
                LegendPosition="ChartLegendPosition.Hidden" />

Static Data Example

A bar chart with three uncolored datasets — colors are filled in from the active Fluent palette. Click any bar to see the click event payload, and toggle the site theme between Light and Dark to see the chart re-theme in place.

Example

AggregateDataverseChartDataSource

Use AggregateDataverseChartDataSource to feed a chart from Dataverse without writing raw FetchXML. Set TableName, GroupByColumn, AggregateColumn, and Aggregate. Optionally add a SeriesColumn for multi-series, a GroupByDateGrouping for date bucketing, a ViewId to merge a saved view's filter conditions, or a FilterXml fragment for inline conditions.

<DataverseChart Source="_source"
                Type="ChartType.Bar"
                Title="Estimated Revenue by Year (Stacked)"
                Stacked="true"
                YAxisPrefix="$"
                OnElementClick="OnBarClicked" />

@code {
    private readonly AggregateDataverseChartDataSource _source = new()
    {
        TableName = "opportunity",
        GroupByColumn = "actualclosedate",
        GroupByDateGrouping = ChartDateGrouping.Year,
        AggregateColumn = "estimatedvalue",
        Aggregate = AggregateType.Sum,
        SeriesColumn = "statecode",
        FilterXml = "<filter><condition attribute='statecode' operator='ne' value='0' /></filter>",
    };

    private void OnBarClicked(ChartClickEventArgs args)
    {
        // args.DatasetLabel, args.Label, args.Value, args.DataPoint
    }
}

Dataverse Example

Estimated opportunity revenue by year, split by status (Won vs Lost) and stacked — loaded from Dataverse via AggregateDataverseChartDataSource. Click a bar to see the year, status, and revenue.

Example

View-Based Filtering

Pass ViewIds and DefaultViewId on DataverseChart to display a view selector dropdown above the chart. When the user switches views, the selected view's filter conditions are merged into the aggregate query and the chart reloads. The ViewId on the source is not set directly — DataverseChart manages it. The view determines which records are included; the aggregate config determines how they're grouped and summarized.

<DataverseChart Source="_source"
                Type="ChartType.Bar"
                ViewIds="_viewIds"
                DefaultViewId="@_defaultViewId"
                YAxisPrefix="$" />

@code {
    private static readonly List<Guid> _viewIds = new()
    {
        new Guid("..."), // Won Opportunities
        new Guid("..."), // All Opportunities
    };

    private static readonly Guid _defaultViewId = _viewIds[0];

    private readonly AggregateDataverseChartDataSource _source = new()
    {
        TableName = "opportunity",
        GroupByColumn = "actualclosedate",
        GroupByDateGrouping = ChartDateGrouping.MonthAndYear,
        AggregateColumn = "estimatedvalue",
        Aggregate = AggregateType.Sum,
    };
}

View-Filtered Example

Estimated revenue by month with a view selector dropdown. Switch between views to see the chart reload with different filter criteria.

Example
All OpportunitiesWon Opportunities

Linked Entity Grouping

Set GroupByLinkedEntity (or SeriesLinkedEntity) to group or split by a column on a related table. The builder creates a <link-entity> join and places the groupby attribute inside it. Supports unlimited nesting via ChartLinkedEntity.LinkedEntity for multi-hop joins.

<DataverseChart Source="_source"
                Type="ChartType.Bar"
                Title="Revenue by Industry"
                YAxisPrefix="$" />

@code {
    private readonly AggregateDataverseChartDataSource _source = new()
    {
        TableName = "opportunity",
        GroupByColumn = "industrycode",
        GroupByLinkedEntity = new ChartLinkedEntity
        {
            TableName = "account",
            From = "accountid",
            To = "customerid",
        },
        AggregateColumn = "estimatedvalue",
        Aggregate = AggregateType.Sum,
    };
}

The above configuration generates the following FetchXML:

<fetch aggregate="true">
  <entity name="opportunity">
    <attribute name="estimatedvalue" alias="estimatedvalue" aggregate="sum" />
    <link-entity name="account" from="accountid" to="customerid" link-type="inner">
      <attribute name="industrycode" alias="industrycode" groupby="true" />
      <order alias="industrycode" />
    </link-entity>
  </entity>
</fetch>

Linked Entity Example

Total estimated opportunity revenue grouped by the parent account's industry — the industrycode column lives on the account table, joined via customerid.

Example

See Also

Chart API Reference — complete documentation for all chart classes, enums, and data sources.