none
Charting with System.Windows.Controls.DataVisualization.Charting

    Question

  • 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

    Monday, July 19, 2010 2:50 PM

Answers

  • 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.
    Thursday, July 22, 2010 7:35 AM

All replies

  • 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.
    Thursday, July 22, 2010 7:35 AM
  • 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, July 22, 2010 2:17 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!

    Thursday, January 19, 2012 4:50 PM
  • I have a similar requirement , but my charting tool kit looks like the following

      <chartingToolkit:ColumnSeries  x:Name="Cong"
                    DependentValuePath="Value"
                    IndependentValuePath="Key"
                    Title="Congestion (WiFi)"
                    ItemsSource="{Binding OBColl}">

    ie I have an Observable collection 'OBColl' in my viewmodel bound to the itemsource of the charttoolkit. My requirement is that the collection has two columns, kind of key and value. The color of the column need to change depending on the value. I am not sure how to call the converter method using the following code.

    <Setter Property="Background" Value="{Binding RelativeSource={RelativeSource Self}, Converter={StaticResource converter}}"/

    I tried using this code but, the data type of 'value' in the converter class shows as ColumnDataPoint and I am not able to extract the

    column from the collection to add logic to change the color. Pls help.

    Thanks in Advance

    Sebastin



    Friday, September 27, 2013 4:28 PM