I have a pie chart on a WPF user control whose data changes periodically, however I am not instantiating a new chart control each time, just clearing the data in the ItemsSource and then inserting new values.
Each time the values get refreshed, the colour palate continues rolling through its colour selections.
The chart colour selection always starts off with the same colour selections (first is red, then blue etc), I would like to be able to tell the chart to restart its colour selection from scratch each time I reset the data source, instead of getting different colours everytime I clear the and reset the data items.
I tried creating a new instance of the ObservableCollection each time but that did not make any difference.
I've got the same problem, and I found another solution. Maybe it's not the better one, but it works.
I added an int property to my object binding on the PieSeries, who represent the element's index in the ObservableCollection. Then I created a ResourceDictionaryCollection which contains all the default colors of the 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 index of ResourceDictionaryCollection.
/// <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 this elements in the Xaml like this:
<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 that answer can help you.
If you don't want to add another property to your data and a converter, you can use reflection.
To aid in easy data presentation, wpftoolkit data series have an inheritable ResourceDictionaryDispenser in charge with providing a different set of resource dictionaries every time it's called. The ResourceDictionaryDispenser in each DataPointSeries gets its own enumerators from the one in the Chart object.
Too bad the ResourceDictionaryDispenser property in Chart is private, as is its Reset() method. You can use the following code, though:
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 stored a reference to the method and the resource dispenser, you should avoid direct binding your data source with the series' ItemsSource. Intercept instead your data update (maybe with the INotifyPropertyChanged.PropertyChanged event) and act like this:
pieDataSeries.ItemsSource = null;
ResDispenserReset.Invoke(resDispenser, null);
pieDataSeries.ItemsSource = [new data set];
tested and 100% working.
The XAML is like this:
<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 should add these usings too.
using System.Reflection;
using System.Windows.Controls.DataVisualization;
using System.Windows.Controls.DataVisualization.Charting;
来源:https://stackoverflow.com/questions/8570850/how-to-reset-the-wpf-toolkit-chart-colour-palette-when-resetting-the-data