How to reset the color palette of a WPF toolkit chart when resetting data

I have a pie chart in a WPF user control whose data changes periodically, however I do not create a new chart control every time, just clearing the data in the ItemsSource and then inserting new values.

Each time the values ​​become updated, the color sky continues to scroll through its color selections.

Chart color selection always starts with the same color choice (first red, then blue, etc.), I would like to say that the chart will resume its color selection from scratch every time I reset the source data, instead of to get different colors every time I clear and reset data items.

I tried to create a new instance of ObservableCollection every time, but that didn't make any difference.

+3
source share
2 answers

I have the same problem and I found another solution. It may not be the best, but it works.

I added an int property to bind objects to PieSeries that represent the index of an element in an ObservableCollection. Then I created a ResourceDictionaryCollection that contains all the colors of the default palette:

<datavis:ResourceDictionaryCollection x:Key="CouleursGraphique"> <!-- Blue --> <ResourceDictionary> <RadialGradientBrush x:Key="Background" GradientOrigin="-0.1,-0.1" Center="0.075,0.015" RadiusX="1.05" RadiusY="0.9"> <GradientStop Color="#FFB9D6F7" /> <GradientStop Color="#FF284B70" Offset="1" /> </RadialGradientBrush> </ResourceDictionary> <!-- Red --> <ResourceDictionary> <RadialGradientBrush x:Key="Background" GradientOrigin="-0.1,-0.1" Center="0.075,0.015" RadiusX="1.05" RadiusY="0.9"> <GradientStop Color="#FFFBB7B5" /> <GradientStop Color="#FF702828" Offset="1" /> </RadialGradientBrush> </ResourceDictionary> <!-- Light Green --> <ResourceDictionary> <RadialGradientBrush x:Key="Background" GradientOrigin="-0.1,-0.1" Center="0.075,0.015" RadiusX="1.05" RadiusY="0.9"> <GradientStop Color="#FFB8C0AC" /> <GradientStop Color="#FF5F7143" Offset="1" /> </RadialGradientBrush> </ResourceDictionary> <!-- Yellow --> <ResourceDictionary> <RadialGradientBrush x:Key="Background" GradientOrigin="-0.1,-0.1" Center="0.075,0.015" RadiusX="1.05" RadiusY="0.9"> <GradientStop Color="#FFFDE79C" /> <GradientStop Color="#FFF6BC0C" Offset="1" /> </RadialGradientBrush> </ResourceDictionary> <!-- Indigo --> <ResourceDictionary> <RadialGradientBrush x:Key="Background" GradientOrigin="-0.1,-0.1" Center="0.075,0.015" RadiusX="1.05" RadiusY="0.9"> <GradientStop Color="#FFA9A3BD" /> <GradientStop Color="#FF382C6C" Offset="1" /> </RadialGradientBrush> </ResourceDictionary> <!-- Magenta --> <ResourceDictionary> <RadialGradientBrush x:Key="Background" GradientOrigin="-0.1,-0.1" Center="0.075,0.015" RadiusX="1.05" RadiusY="0.9"> <GradientStop Color="#FFB1A1B1" /> <GradientStop Color="#FF50224F" Offset="1" /> </RadialGradientBrush> </ResourceDictionary> <!-- Dark Green --> <ResourceDictionary> <RadialGradientBrush x:Key="Background" GradientOrigin="-0.1,-0.1" Center="0.075,0.015" RadiusX="1.05" RadiusY="0.9"> <GradientStop Color="#FF9DC2B3" /> <GradientStop Color="#FF1D7554" Offset="1" /> </RadialGradientBrush> </ResourceDictionary> <!-- Gray Shade --> <ResourceDictionary> <RadialGradientBrush x:Key="Background" GradientOrigin="-0.1,-0.1" Center="0.075,0.015" RadiusX="1.05" RadiusY="0.9"> <GradientStop Color="#FFB5B5B5" /> <GradientStop Color="#FF4C4C4C" Offset="1" /> </RadialGradientBrush> </ResourceDictionary> <!-- Blue --> <ResourceDictionary> <RadialGradientBrush x:Key="Background" GradientOrigin="-0.1,-0.1" Center="0.075,0.015" RadiusX="1.05" RadiusY="0.9"> <GradientStop Color="#FF98C1DC" /> <GradientStop Color="#FF0271AE" Offset="1" /> </RadialGradientBrush> </ResourceDictionary> <!-- Brown --> <ResourceDictionary> <RadialGradientBrush x:Key="Background" GradientOrigin="-0.1,-0.1" Center="0.075,0.015" RadiusX="1.05" RadiusY="0.9"> <GradientStop Color="#FFC1C0AE" /> <GradientStop Color="#FF706E41" Offset="1" /> </RadialGradientBrush> </ResourceDictionary> <!-- Cyan --> <ResourceDictionary> <RadialGradientBrush x:Key="Background" GradientOrigin="-0.1,-0.1" Center="0.075,0.015" RadiusX="1.05" RadiusY="0.9"> <GradientStop Color="#FFADBDC0" /> <GradientStop Color="#FF446A73" Offset="1" /> </RadialGradientBrush> </ResourceDictionary> <!-- Special Blue --> <ResourceDictionary> <RadialGradientBrush x:Key="Background" GradientOrigin="-0.1,-0.1" Center="0.075,0.015" RadiusX="1.05" RadiusY="0.9"> <GradientStop Color="#FF2F8CE2" /> <GradientStop Color="#FF0C3E69" Offset="1" /> </RadialGradientBrush> </ResourceDictionary> <!-- Gray Shade 2 --> <ResourceDictionary> <RadialGradientBrush x:Key="Background" GradientOrigin="-0.1,-0.1" Center="0.075,0.015" RadiusX="1.05" RadiusY="0.9"> <GradientStop Color="#FFDCDCDC" /> <GradientStop Color="#FF757575" Offset="1" /> </RadialGradientBrush> </ResourceDictionary> <!-- Gray Shade 3 --> <ResourceDictionary> <RadialGradientBrush x:Key="Background" GradientOrigin="-0.1,-0.1" Center="0.075,0.015" RadiusX="1.05" RadiusY="0.9"> <GradientStop Color="#FFF4F4F4" /> <GradientStop Color="#FFB7B7B7" Offset="1" /> </RadialGradientBrush> </ResourceDictionary> <!-- Gray Shade 4 --> <ResourceDictionary> <RadialGradientBrush x:Key="Background" GradientOrigin="-0.1,-0.1" Center="0.075,0.015" RadiusX="1.05" RadiusY="0.9"> <GradientStop Color="#FFF4F4F4" /> <GradientStop Color="#FFA3A3A3" Offset="1" /> </RadialGradientBrush> </ResourceDictionary> </datavis:ResourceDictionaryCollection> 

I added a converter that returns the color at the specified ResourceDictionaryCollection index.

  /// <summary> /// Convertit une valeur. /// </summary> /// <param name="value">Valeur produite par la source de liaison.</param> /// <param name="targetType">Type de la propriété de cible de liaison.</param> /// <param name="parameter">Paramètre de convertisseur à utiliser.</param> /// <param name="culture">Culture à utiliser dans le convertisseur.</param> /// <returns> /// Une valeur convertie. Si la méthode retourne null, la valeur Null valide est utilisée. /// </returns> public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) { ResourceDictionaryCollection listeCouleurs = parameter as ResourceDictionaryCollection; int indice = (int)value; return listeCouleurs[indice % listeCouleurs.Count]["Background"]; } 

And I used all of these elements in Xaml as follows:

  <charting:Chart.Series> <charting:PieSeries ItemsSource="{Binding Path=Donnees}" DependentValuePath="Valeur" IndependentValuePath="Libelle"> <charting:PieSeries.Palette> <datavis:ResourceDictionaryCollection> <ResourceDictionary> <Style x:Key="DataPointStyle" TargetType="Control"> <Setter Property="Background" Value="{Binding Path=Index, Converter={StaticResource convCouleur}, ConverterParameter={StaticResource CouleursGraphique}}"/> </Style> </ResourceDictionary> </datavis:ResourceDictionaryCollection> </charting:PieSeries.Palette> </charting:PieSeries> 

I hope the answer can help you.

+4
source

If you do not want to add another property to your data and converter, you can use reflection.

To facilitate easy presentation of data, wpftoolkit data series have an inheritable ResourceDictionaryDispenser responsible for providing a different set of resource dictionaries each time it is called. ResourceDictionaryDispenser in each DataPointSeries gets its own enumerations from the object in the Chart .

Too bad, the ResourceDictionaryDispenser property in Chart is private, like its Reset() method. You can use the following code:

 Type t = typeof(Chart); PropertyInfo fResDispenser = t.GetProperty("ResourceDictionaryDispenser", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.GetProperty); resDispenser = fResDispenser.GetValue(chart, null); ResDispenserReset = resDispenser.GetType().GetMethod("Reset", BindingFlags.NonPublic | BindingFlags.Instance); ResDispenserReset.Invoke(resDispenser, null); 

Once you have saved the reference to the method and the resource distributor, you should avoid directly linking the data source to the ItemsSource series. Instead, intercept the data update (possibly with the INotifyPropertyChanged.PropertyChanged event) and do the following:

 pieDataSeries.ItemsSource = null; ResDispenserReset.Invoke(resDispenser, null); pieDataSeries.ItemsSource = [new data set]; 

and 100% works.

XAML is as follows:

 <UserControl x:Class="Datamanager.Widgets.SubunitsPieChart" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:gra="clr-namespace:System.Windows.Controls.DataVisualization.Charting;assembly=System.Windows.Controls.DataVisualization.Toolkit"> <gra:Chart Margin="5" x:Name="chart" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" BorderThickness="0"> <gra:PieSeries x:Name="chartSeries" DependentValuePath="Value" IndependentValuePath="Key" /> </gra:Chart> </UserControl> 

you must also add these using .

 using System.Reflection; using System.Windows.Controls.DataVisualization; using System.Windows.Controls.DataVisualization.Charting; 
+1
source

All Articles