Skip to main content

Theme river chart

info

Charts are available with Avalonia Pro.

Theme river charts visualize changes in categories over time. In Avalonia.Controls.Charts, this layout can be built by combining multiple StackedAreaSeries instances inside a CartesianChart.

Theme river chart with stacked organic stream bands showing how category volumes flow and change over time.

When to use

  • Topic trends: Visualizing the popularity of themes in news or social media over time.
  • Resource allocation: Showing how budget or manpower shifts between projects.
  • Usage patterns: Tracking the volume of different types of network traffic.

Code example

XAML

<charts:CartesianChart Name="ThemeRiverSample" Title="Data Stream" Height="400"
ShowLegend="True" LegendPosition="Bottom">
<charts:CartesianChart.Series>
<!-- Dummy Series (Transparent Spacer for Wiggle/Centering) -->
<charts:StackedAreaSeries Title="" ItemsSource="{Binding ThemeRiverDummy}"
CategoryPath="Category" ValuePath="Value"
StackGroup="River"
Fill="Transparent"
StrokeThickness="0" />

<!-- Visible Data Series -->
<charts:StackedAreaSeries Title="Stream A" ItemsSource="{Binding ThemeRiverSeriesA}"
CategoryPath="Category" ValuePath="Value"
StackGroup="River"
Fill="#FF6B6B" Stroke="#E05555" StrokeThickness="1" />

<charts:StackedAreaSeries Title="Stream B" ItemsSource="{Binding ThemeRiverSeriesB}"
CategoryPath="Category" ValuePath="Value"
StackGroup="River"
Fill="#4ECDC4" Stroke="#3EBDB4" StrokeThickness="1" />

<charts:StackedAreaSeries Title="Stream C" ItemsSource="{Binding ThemeRiverSeriesC}"
CategoryPath="Category" ValuePath="Value"
StackGroup="River"
Fill="#FFE66D" Stroke="#EED55D" StrokeThickness="1" />
</charts:CartesianChart.Series>

<charts:CartesianChart.HorizontalAxis>
<charts:CategoryAxis ShowGridLines="False" />
</charts:CartesianChart.HorizontalAxis>

<charts:CartesianChart.VerticalAxis>
<charts:NumericalAxis ShowGridLines="False" IsVisible="False" />
</charts:CartesianChart.VerticalAxis>
</charts:CartesianChart>

Data model (C#)

using System.Collections.Generic;

public class ThemeRiverViewModel
{
public List<ThemeRiverItem> ThemeRiverDummy { get; } = new();
public List<ThemeRiverItem> ThemeRiverSeriesA { get; } = new();
public List<ThemeRiverItem> ThemeRiverSeriesB { get; } = new();
public List<ThemeRiverItem> ThemeRiverSeriesC { get; } = new();

public ThemeRiverViewModel()
{
GenerateThemeRiverData();
}

private void GenerateThemeRiverData()
{
const int count = 30;
const double center = 50.0;

for (var i = 0; i < count; i++)
{
var category = $"T{i}";
var streamA = 10 + 5 * System.Math.Sin(i * 0.3);
var streamB = 15 + 8 * System.Math.Sin(i * 0.5 + 1);
var streamC = 12 + 6 * System.Math.Cos(i * 0.4);
var offset = center - (streamA + streamB + streamC) / 2;

ThemeRiverDummy.Add(new ThemeRiverItem { Category = category, Value = offset });
ThemeRiverSeriesA.Add(new ThemeRiverItem { Category = category, Value = streamA });
ThemeRiverSeriesB.Add(new ThemeRiverItem { Category = category, Value = streamB });
ThemeRiverSeriesC.Add(new ThemeRiverItem { Category = category, Value = streamC });
}
}
}

public class ThemeRiverItem
{
public string Category { get; set; } = string.Empty;
public double Value { get; set; }
}

Common properties (StackedAreaSeries)

PropertyDescriptionDefault
TitleSeries name shown in the legend.null
ItemsSourceThe collection of data points for a single stream.null
CategoryPathProperty used for the horizontal category or time bucket.null
ValuePathProperty determining the thickness of the stream.null
StackGroupStack group shared by the related area series.null
FillBrush used for the stream area.Theme-dependent
StrokeBrush used for the stream outline.Theme-dependent