Nested Pies
This sample uses C# 13 preview features such as partial properties, it also uses features from the CommunityToolkit.Mvvm package, you can learn more about it here.
This web site wraps every sample using a UserControl instance, but LiveCharts controls can be used inside any container.
View model
using System;
using System.Linq;
using LiveChartsCore.Kernel;
namespace ViewModelsSamples.Pies.Nested;
public class SalesRecord(string country, string zone, string name, double value)
{
public string Country { get; set; } = country;
public string Zone { get; set; } = zone;
public string Name { get; set; } = name;
public double Value { get; set; } = value;
}
public class PieData(string name, double?[] values, string color)
{
public string Name { get; set; } = name;
public double?[] Values { get; set; } = values;
public string Color { get; set; } = color;
public bool IsTotal => Name is "Brazil" or "Colombia" or "Mexico";
public Func<ChartPoint, string> Formatter { get; } = point =>
$"{name}{Environment.NewLine}{point.StackedValue!.Share:P2}";
}
public class ViewModel
{
public SalesRecord[] Data { get; set; } = [
new("Brazil", "North", "John", 10),
new("Brazil", "North", "Mary", 5),
new("Brazil", "South", "John", 20),
new("Brazil", "South", "Mary", 8),
new("Colombia", "East", "Carla", 15),
new("Colombia", "East", "Charles", 15),
new("Colombia", "West", "Carla", 25),
new("Colombia", "West", "Charles", 25),
new("Mexico", "Central", "Sophia", 30),
new("Mexico", "Central", "Petter", 5),
new("Mexico", "North", "Sophia", 30),
new("Mexico", "North", "Petter", 5)
];
public PieData[] PieDataCollection { get; set; }
public ViewModel()
{
PieDataCollection = [
new("Brazil", [null, null, Sum("Brazil")], "#1976d2"),
new("North", [null, Sum("Brazil", "North"), null], "#1e88e5"),
new("John", [Sum("Brazil", "North", "John"), null, null], "#2196f3"),
new("Mary", [Sum("Brazil", "North", "Mary"), null, null], "#42a5f5"),
new("South", [null, Sum("Brazil", "South"), null], "#64b5f6"),
new("John", [Sum("Brazil", "South", "John"), null, null], "#90caf9"),
new("Mary", [Sum("Brazil", "South", "Mary"), null, null], "#bbdefb"),
new("Colombia", [null, null, Sum("Colombia")], "#d32f2f"),
new("East", [null, Sum("Colombia", "East"), null], "#e53935"),
new("Carla", [Sum("Colombia", "East", "Carla"), null, null], "#f44336"),
new("Charles", [Sum("Colombia", "East", "Charles"),null, null], "#ef5350"),
new("West", [null, Sum("Colombia", "West"), null], "#e57373"),
new("Carla", [Sum("Colombia", "West", "Carla"), null, null], "#ef9a9a"),
new("Charles", [Sum("Colombia", "West", "Charles"),null, null], "#ffcdd2"),
new("Mexico", [null, null, Sum("Mexico")], "#ffa000"),
new("Central", [null, Sum("Mexico", "Central"), null], "#ffb300"),
new("Sophia", [Sum("Mexico", "Central", "Sophia"),null, null], "#ffc107"),
new("Petter", [Sum("Mexico", "Central", "Petter"),null, null], "#ffca28"),
new("North", [null, Sum("Mexico", "North"), null], "#ffd54f"),
new("Sophia", [Sum("Mexico", "North", "Sophia"), null, null], "#ffe082"),
new("Petter", [Sum("Mexico", "North", "Petter"), null, null], "#ffecb3")
];
}
public double Sum(string country, string? zone = null, string? name = null)
{
return Data
.Where(x =>
(country is null || x.Country == country) &&
(zone is null || x.Zone == zone) &&
(name is null || x.Name == name))
.Sum(x => x.Value);
}
}
XAML
<UserControl
x:Class="WinUISample.Pies.Nested.View"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:lvc="using:LiveChartsCore.SkiaSharpView.WinUI"
xmlns:vms="using:ViewModelsSamples.Pies.Nested"
xmlns:local="using:WinUISample.Pies.Nested"
mc:Ignorable="d">
<UserControl.DataContext>
<vms:ViewModel/>
</UserControl.DataContext>
<UserControl.Resources>
<local:StringToPaintConverter x:Key="StringToPaintConverter"/>
</UserControl.Resources>
<lvc:PieChart InitialRotation="120" SeriesSource="{Binding PieDataCollection}" LegendPosition="Right">
<lvc:PieChart.SeriesTemplate>
<DataTemplate>
<lvc:XamlPieSeries
SeriesName="{Binding Name}"
Values="{Binding Values}"
Stroke="{lvc:SolidColorPaint Color='#fff', StrokeWidth=2}"
Fill="{Binding Color, Converter={StaticResource StringToPaintConverter}}"
HoverPushout="0"
DataLabelsFormatter="{Binding Formatter}"
DataLabelsSize="20"
ShowDataLabels="{Binding IsTotal}"
DataLabelsPosition="Outer"
IsVisibleAtLegend="{Binding IsTotal}">
</lvc:XamlPieSeries>
</DataTemplate>
</lvc:PieChart.SeriesTemplate>
</lvc:PieChart>
</UserControl>
StringToPaintConverter.cs
using System;
using System.Globalization;
using Microsoft.UI.Xaml.Data;
using LiveChartsCore.SkiaSharpView.Painting;
using SkiaSharp;
namespace WinUISample.Pies.Nested;
public class StringToPaintConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, string language)
{
if (value is string colorString)
return new SolidColorPaint(SKColor.Parse(colorString));
return null;
}
public object ConvertBack(object value, Type targetType, object parameter, string language)
{
if (value is SolidColorPaint paint)
{
var c = paint.Color;
return $"#{c.Red:X2}{c.Green:X2}{c.Blue:X2}";
}
return null;
}
}