how to set pie chart series colors?

2 Answers 9 Views
Chart
Robbe
Top achievements
Rank 1
Iron
Iron
Robbe asked on 07 Nov 2025, 06:19 PM
I don't want to use the colors in the them.  I want to set them myself for each DataItem.  How is that done in a pie chart?

2 Answers, 1 is accepted

Sort by
0
Didi
Telerik team
answered on 09 Nov 2025, 05:04 PM

Hi Robbe,

For this scenario you need to create a custom chart palette for the pie chart and override the default palette values.

Here is the approach:

1. Add a color property to the data model:

public class DataItem
    {
        public string Category { get; set; }
        public double? Value { get; set; }
        public Color pieColor { get; set; }
    }
2. Define sample view model and in the collection set values for the pie color:
public class ViewModel
{
	public ObservableCollection<DataItem> SeriesData { get; set; }

	public ViewModel()
	{
		var seriesData = new ObservableCollection<DataItem>()
			{
				new DataItem(){Category = "Greenings", Value = 85, pieColor = Color.FromRgba("#F8F8F8")},
				new DataItem(){Category = "Perfecto", Value = 78, pieColor = Color.FromRgba("#F8A8F8")},
				new DataItem(){Category = "NearBy", Value = 99, pieColor = Color.FromRgba("#F8F808")},
				new DataItem(){Category = "FamilyStore", Value = 85, pieColor = Color.FromRgba("#B8F8F8")},
				new DataItem(){Category = "Fresh&Green", Value = 57, pieColor = Color.FromRgba("#000000")}
			};
		this.SeriesData = seriesData;
	}
}

3. Create a custom class with an attached property. The pill be used to replace the default palette colors with the custom:

public static class ChartUtils
{
	public static readonly BindableProperty ColorsSourceProperty = BindableProperty.CreateAttached("ColorsSource", typeof(IEnumerable), typeof(ChartUtils), null,
		propertyChanged: OnColorsSourceChanged);

	public static IEnumerable GetColorsSource(BindableObject bindableObject)
	{
		return (IEnumerable)bindableObject.GetValue(ColorsSourceProperty);
	}

	public static void SetColorsSource(BindableObject bindableObject, IEnumerable value)
	{
		bindableObject.SetValue(ColorsSourceProperty, value);
	}

	private static void OnColorsSourceChanged(BindableObject bindable, object oldValue, object newValue)
	{
		IEnumerable newColorsSource = (IEnumerable)newValue;
		RadPieChart chart = (RadPieChart)bindable;
		chart.Palette = ToChartPalette(newColorsSource);
	}

	private static ChartPalette ToChartPalette(IEnumerable colorsSource)
	{
		ChartPalette chartPalette = new ChartPalette();

		if (colorsSource != null)
		{
			foreach (var item in colorsSource)
			{
				if (item is DataItem dataItem)
				{
					PaletteEntry entry = new PaletteEntry();
					entry.FillColor = dataItem.pieColor;
					entry.StrokeColor = dataItem.pieColor;
					chartPalette.Entries.Add(entry);
				}
			}
		}

		return chartPalette;
	}
}

4. Set the attached property to the PieChart:

<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
             xmlns:telerik="http://schemas.telerik.com/2022/xaml/maui"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
			 xmlns:local="clr-namespace:MauiApp9"
             x:Class="MauiApp9.MainPage">

	<Grid RowDefinitions="400,100">
		<telerik:RadPieChart x:Name="chartTest" local:ChartUtils.ColorsSource="{Binding SeriesData}">
			<telerik:RadPieChart.Series>
				<telerik:PieSeries ShowLabels="True"
									RadiusFactor="0.8"
									ValueBinding="Value"
									ItemsSource="{Binding SeriesData}" />
			</telerik:RadPieChart.Series>
			<telerik:RadPieChart.BindingContext>
				<local:ViewModel />
			</telerik:RadPieChart.BindingContext>
		</telerik:RadPieChart>
	</Grid>
</ContentPage>

And this is the result on andorid:

I hope all details and sample code will be of help.

Regards,
Didi
Progress Telerik

Love the Telerik and Kendo UI products and believe more people should try them? Invite a fellow developer to become a Progress customer and each of you can get a $50 Amazon gift voucher.


Robbe
Top achievements
Rank 1
Iron
Iron
commented on 10 Nov 2025, 02:14 PM

This does not really work.  Its creating a new instance of the ViewModel and not using the instance in the BindingContext of the ContentPage.  Thus, when the OnColorsSourceChanged fires, my collections are empty.  I had to take the reference to the BindingContext tag out of your sample for that reason.   My ViewModel has dependencies.  If I remove this:  utils:ChartUtils.ColorsSource="{Binding Progress.Historical.Items}", the chart renders properly but uses the default theme colors.  If I put it in, the collections are empty and still reflect the default theming colors.

 

xmlns:utils="clr-namespace:CheckList.Utils"

 

    <telerik:RadPieChart Style="{StaticResource ProgressChartWrap}" utils:ChartUtils.ColorsSource="{Binding Progress.Historical.Items}">
        <telerik:RadPieChart.ChartBehaviors>
            <telerik:ChartSelectionBehavior DataPointSelectionMode="Single"  SeriesSelectionMode="None" />
        </telerik:RadPieChart.ChartBehaviors>
        <telerik:RadPieChart.Series>
            <telerik:PieSeries ItemsSource="{Binding Progress.Historical.Items}"  ValueBinding="Value" RadiusFactor="0.9" LegendTitleBinding="Category" />
        </telerik:RadPieChart.Series>
    </telerik:RadPieChart>
    <Label Text="Historical Data" Style="{StaticResource CheckListLabel}" />
</HorizontalStackLayout>

Didi
Telerik team
commented on 10 Nov 2025, 04:04 PM

Hi Robbe,

I tested setting the binding context to the page and removed it from the chart and still the chart custom colors apply as expected. I have attached the xaml and cs files. Download and test on your side in your sample app.  For sure you have some additional setting and code implementation. Send an updated version of the xaml and cs files, so I can test on my side.

0
Robbe
Top achievements
Rank 1
Iron
Iron
answered on 10 Nov 2025, 07:28 PM

Here are the changes I made to the class to make it work in my app.  Also, there is no need to set the binding context for the RadPieChart in the xaml.  Appreciate all your help with this.

using System.Collections;
using System.Collections.ObjectModel;
using System.Collections.Specialized;
using Microsoft.Maui.Controls;
using Microsoft.Maui.Graphics;
using Telerik.Maui.Controls.Compatibility.Chart;
using CheckList.DataObjects.Tables;

namespace CheckList.Utils
{
    public static class ChartUtils
    {
        public static readonly BindableProperty ColorsSourceProperty =
            BindableProperty.CreateAttached(
                "ColorsSource",
                typeof(IEnumerable),
                typeof(ChartUtils),
                default(IEnumerable),
                propertyChanged: OnColorsSourceChanged);
 
        public static IEnumerable GetColorsSource(BindableObject bindable) =>
            (IEnumerable)bindable.GetValue(ColorsSourceProperty);

        public static void SetColorsSource(BindableObject bindable, IEnumerable value) =>
            bindable.SetValue(ColorsSourceProperty, value);
 
        private static readonly BindableProperty ColorsSubscriptionProperty =
            BindableProperty.CreateAttached(
                "ColorsSub",
                typeof(INotifyCollectionChanged),
                typeof(ChartUtils),
                default(INotifyCollectionChanged));

        private static void OnColorsSourceChanged(BindableObject bindable, object oldValue, object newValue)
        {
 
            if (bindable is not RadPieChart chart)
                return;
 
            if (oldValue is INotifyCollectionChanged oldIncc)
            {
                oldIncc.CollectionChanged -= (_, __) => {};  
                TryDetachCollectionChanged(chart, oldIncc);
            }
 
            ApplyPalette(chart, newValue as IEnumerable);
 
            if (newValue is INotifyCollectionChanged incc)
            {
                AttachCollectionChanged(chart, incc);
            }
        }

        private static void ApplyPalette(RadPieChart chart, IEnumerable colorsSource)
        {
            var palette = new ChartPalette();

            if (colorsSource != null)
            {
                foreach (var item in colorsSource)
                {
                    Color color;

                    if (item is DataItem di)
                        color = di.PieColor;
                    else if (item is Color c)
                        color = c;
                    else
                        continue;

                    palette.Entries.Add(new PaletteEntry
                    {
                        FillColor = color,
                        StrokeColor = color
                    });
                }
            }

            chart.Palette = palette;
        }

        private static void AttachCollectionChanged(RadPieChart chart, INotifyCollectionChanged incc)
        {
 
            chart.SetValue(ColorsSubscriptionProperty, incc);
 
            incc.CollectionChanged += CollectionChangedHandler;
            void CollectionChangedHandler(object sender, NotifyCollectionChangedEventArgs e)
            {
                var src = GetColorsSource(chart) as IEnumerable;
                ApplyPalette(chart, src);
            }
 
            chart.BindingContextChanged += Chart_BindingContextChanged;
            void Chart_BindingContextChanged(object s, System.EventArgs e)
            {
                var src = GetColorsSource(chart) as IEnumerable;
                ApplyPalette(chart, src);
            }
        }

        private static void TryDetachCollectionChanged(RadPieChart chart, INotifyCollectionChanged oldIncc)
        {
            chart.BindingContextChanged -= Chart_BindingContextChanged_NoOp;

            static void Chart_BindingContextChanged_NoOp(object s, System.EventArgs e) { }
        }
    }
}

Tags
Chart
Asked by
Robbe
Top achievements
Rank 1
Iron
Iron
Answers by
Didi
Telerik team
Robbe
Top achievements
Rank 1
Iron
Iron
Share this question
or