Charting with System.Windows.Controls.DataVisualization.Charting
-
Monday, July 19, 2010 2:50 PM
Hi,
I'm having kind of a hard time getting started with the charting library included in the WPF Toolkit. I've tried to find the answer in these forums, in the WPF Toolkit discussions and in this well written article http://expression.microsoft.com/en-us/dd433476.aspx
What I want to show in the graph
I've got an object holding the data I want to display
public class SIPMessageStatisticDto { public int TotalMessageCount { get; set; } public int AllErrorMessageCount { get; set; } public int ManufacturerErrorMessageCount { get; set; } public int TypeErrorMessageCount { get; set; } public int ModelErrorMessageCount { get; set; } public int DeviceErrorMessageCount { get; set; } }
For each accessor in this object I'd like to draw a bar (each bar with a different colour) that is structured as follows:
Name of the entry (provided by another object), bar showing the percentage of error messages (100 * xxxErrorMessageCount / TotalMessageCount), percentage value, xxxErrorMessageCount
Question
I'm currently stuck at how to start this in order to have a different colour for each bar. Do I have to define a new BarSeries for each entry? (If I bind an object implementing System.Collections.ObjectModel.Collection<T> multiple entries are shown, but all the bars got the same colour).My problem seems to be related to some fundamental understandings of how this library works. I hope someone can point me into the right directions.
Thanks, Philippe
All Replies
-
Thursday, July 22, 2010 7:35 AMModerator
Hi ph_waeber ,
First, BarSeries gets a Collection object that can sequence to series data to draw the bar. So we should create a Collection object that set it to BarSeries.ItemsSource. Such as below:
public class SIPMessageStatisticDto : ObservableCollection<KeyValuePair<string, int>> { public int TotalMessageCount { get; set; } public int AllErrorMessageCount { get; set; } public int ManufacturerErrorMessageCount { get; set; } public int TypeErrorMessageCount { get; set; } public int ModelErrorMessageCount { get; set; } public int DeviceErrorMessageCount { get; set; } public SIPMessageStatisticDto() { AddItems(); } public SIPMessageStatisticDto Refresh() { Clear(); AddItems(); return this; } private void AddItems() { Add(new KeyValuePair<string, int>("Total Message", TotalMessageCount)); Add(new KeyValuePair<string, int>("All Error Message", AllErrorMessageCount)); Add(new KeyValuePair<string, int>("Manufacturer Error Message", ManufacturerErrorMessageCount)); Add(new KeyValuePair<string, int>("Type Error Message", TypeErrorMessageCount)); Add(new KeyValuePair<string, int>("Model Error Message", ModelErrorMessageCount)); Add(new KeyValuePair<string, int>("Device Error Message", DeviceErrorMessageCount)); } }
and in the windows:
series.ItemsSource = new SIPMessageStatisticDto() { TotalMessageCount = 100, AllErrorMessageCount = 10, ManufacturerErrorMessageCount = 20, TypeErrorMessageCount = 20, ModelErrorMessageCount = 30, DeviceErrorMessageCount = 20 }.Refresh();------------------------------------
Q:How to start this in order to have a different colour for each bar?
In WPF toolkit Chart, each series has a DataPointStyle property which allows us to define the custom style for the data.
<chartingToolkit:BarSeries.DataPointStyle> <Style TargetType="chartingToolkit:BarDataPoint"> <Setter Property="Background" Value="Green"/> </Style> </chartingToolkit:BarSeries.DataPointStyle>So we need to set the color for each bar. Here we can sue data binding to bind the background to the property of the item, and can convert the item value to a brush value.
<Window.Resources> <l:ConvertToBrush x:Key="converter"/> </Window.Resources> <Grid> <chartingToolkit:Chart Name="chart1"> <chartingToolkit:Chart.Series> <chartingToolkit:BarSeries x:Name="series" DependentValueBinding="{Binding Value}" IndependentValueBinding="{Binding Key}"> <chartingToolkit:BarSeries.DataPointStyle> <Style TargetType="chartingToolkit:BarDataPoint"> <Setter Property="Background" Value="{Binding RelativeSource={RelativeSource Self}, Converter={StaticResource converter}}"/> </Style> </chartingToolkit:BarSeries.DataPointStyle> </chartingToolkit:BarSeries> </chartingToolkit:Chart.Series> </chartingToolkit:Chart> </Grid>
and the code:
public class ConvertToBrush : IValueConverter { public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) { Random random = new Random(DateTime.Now.Millisecond); Color color = Color.FromArgb(255, (byte)random.Next(255), (byte)random.Next(255), (byte)random.Next(255)); return new SolidColorBrush(color); } public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) { throw new NotImplementedException(); }
Sincerely,
Bob Bao
Please remember to mark the replies as answers if they help and unmark them if they provide no help.- Marked As Answer by Bob_BaoMVP, Moderator Thursday, July 29, 2010 1:31 AM
-
Thursday, July 22, 2010 2:17 PM
Hi Bob,
Thanks a lot for your explanations. Unfortunately I wont be able to apply it in the next two weeks, but after that I'll come back to this post
Thanks, Philippe
-
Thursday, January 19, 2012 4:50 PM
Hello Bob and all who've contributed to this post.
I'm working on something a bit similar to this, but instead of using random values for the colors, I am testing the Value and changing the background color based off of that.
public class BarBackgroundConverter : IValueConverter { public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) { //Random random = new Random(DateTime.Now.Millisecond); //Color color = Color.FromArgb(255, (byte)random.Next(255), (byte)random.Next(255), (byte)random.Next(255)); //return new SolidColorBrush(color); if ((value == null) || !(value is BarDataPoint)) return Brushes.Blue; BarDataPoint dataPoint = value as BarDataPoint; double dataValue = (double)dataPoint.ActualDependentValue; return (dataValue >= 0.0) ? Brushes.Blue : Brushes.Red; } public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) { throw new NotImplementedException(); } }Unfortunately though, the dataValue is always 0.0.
I'm going to switch this out for a 3d Barchart instead because I've not found a fix to this.
Any Ideas?
Thanks ahead of time!

