This is a migrated thread and some comments may be shown as answers.

Multiple Y-axis (dynamic) + MVVM

2 Answers 88 Views
Chart
This is a migrated thread and some comments may be shown as answers.
Tobias Rodewi
Top achievements
Rank 1
Tobias Rodewi asked on 19 Aug 2011, 04:04 PM
I've got a chart set up using SeriesMappings on my viewmodel. The user is to be able to select which data (different types) he is to view in the chart as one time, and therefore I also need multiple Y-axis.

Since there's no "default" data which is always shown, I also have to let the RadChart know which axis is the default one. Now I've tried binding the AxisName in XAML to a string property in my viewmodel, matching the name set on the seriesmapping and therefore hint which series is to be used as the default one but the scaling is all wrong.

<chart:ChartArea.AxisY>
  <chart:AxisY AxisName="{Binding DefaultYAxisName, Mode=OneWay}"/>
</chart:ChartArea.AxisY>

I've also tried binding the AxisY property of the RadChart to a property in the viewmodel, but this just results in an "Object reference not set to an instance of an object"-exception and I'm unable to get a working TargetNullValue set up.

The additional y-axes works just fine and scales correctly binding the AddisionalYAxes to a property returning an AxisYCollection.

RadChart (view)
<RadChart x:Name="radChart"
 ItemsSource="{Binding DisplayedConsumptionData, Mode=OneWay}"
 SeriesMappings="{Binding SeriesMappings, Mode=OneWay}" >
.....
<chart:ChartArea LegendName="chartLegend"
  AxisY="{Binding DefaultYAxis, Mode=OneWay}"
  AdditionalYAxes="{Binding YAxes, Mode=OneWay}" />
</RadChart>

Default Y-axis (VM)
private AxisY _defaultYAxis;
public AxisY DefaultYAxis
{
    get { return _defaultYAxis ?? (_defaultYAxis = new AxisY()); }
    set
    {
        if (_defaultYAxis != value)
        {
            _defaultYAxis = value;
            OnPropertyChanged("DefaultYAxis");
        }
    }
}

Collection of additional Y-axis (VM)
private AxisYCollection _yAxes;
public AxisYCollection YAxes
{
 get { return _yAxes ?? (_yAxes = new AxisYCollection()); }
 set
 {
  if (_yAxes != value)
  {
   _yAxes = value;
   OnPropertyChanged("YAxes");
  }
 }
}


SeriesMappings (VM)

private SeriesMappingCollection _seriesMappings;
public
SeriesMappingCollection SeriesMappings
{
 get
 {
  if(_seriesMappings == null)
   _seriesMappings = new SeriesMappingCollection();
  else
   _seriesMappings.Clear();
  
  if (_yAxes == null)
   _yAxes = new AxisYCollection();
  else
   _yAxes.Clear();
  
  _defaultYAxis = null;
 
  foreach (var collection in _displayedConsumptionData)
  {
   #region Type #1 (bar)
   if (_currentCustomization.ShowType1)
   {
    if (_defaultYAxis == null)
     _defaultYAxis = new AxisY
          {
           AxisName = "Type1",
           Title = "Type1Title",
          };
 
    var type1Mapping = new SeriesMapping
        {
         CollectionIndex = _displayedConsumptionData.IndexOf(collection),
         LegendLabel = collection.FirstOrDefault().Title,
         SeriesDefinition =
          new BarSeriesDefinition
           {
            ShowItemToolTips = AllValuesHidden,
            ShowItemLabels = !AllValuesHidden,
            AxisName = "Type1"
           }
        };
 
    type1Mapping.ItemMappings.Add(new ItemMapping
          {
           DataPointMember = DataPointMember.YValue,
           FieldName = "Value"
          });
 
    type1Mapping.ItemMappings.Add(new ItemMapping
          {
           DataPointMember = DataPointMember.XCategory,
           FieldName = "DateTime"
          });
 
    type1Mapping.ItemMappings.Add(new ItemMapping
          {
           DataPointMember = DataPointMember.LegendLabel,
           FieldName = "Title"
          });
    _seriesMappings.Add(type1Mapping);
   }
 
   #endregion
 
   #region Type2 (stacked bar)
   if (_currentCustomization.ShowCost)
   {
    if (_defaultYAxis == null)
     _defaultYAxis = new AxisY
     {
      AxisName = "Type21",
      Title = "Type2Title"
     };
    else
     _yAxes.Add(new AxisY
     {
      AxisName = "Type21",
      Title = "Type2Title"
     });
 
    var type21Mapping =
     new SeriesMapping
      {
       CollectionIndex = _displayedConsumptionData.IndexOf(collection),
       LegendLabel = collection.FirstOrDefault().Title + " (Type2.1)",
       SeriesDefinition =
        new StackedBarSeriesDefinition(
        collection.FirstOrDefault().Title)
         {
          ShowItemToolTips = AllValuesHidden,
          ShowItemLabels = !AllValuesHidden,
          AxisName = "Type21"
         }
      };
 
    type21Mapping.ItemMappings.Add(new ItemMapping
              {
               DataPointMember = DataPointMember.YValue,
               FieldName = "VariableCost"
              });
 
    type21Mapping.ItemMappings.Add(new ItemMapping
              {
               DataPointMember = DataPointMember.XCategory,
               FieldName = "DateTime"
              });
 
    type21Mapping.ItemMappings.Add(new ItemMapping
              {
               DataPointMember = DataPointMember.LegendLabel,
               FieldName = "Title"
              });
    _seriesMappings.Add(type21Mapping);
 
 
 
    var type22Mapping = new SeriesMapping
     {
      CollectionIndex = _displayedConsumptionData.IndexOf(collection),
      LegendLabel = collection.FirstOrDefault().Title + " (Type2.2)",
      SeriesDefinition =
       new StackedBarSeriesDefinition(collection.FirstOrDefault().Title)
      {
        ShowItemToolTips = AllValuesHidden,
        ShowItemLabels = !AllValuesHidden,
        AxisName = "Type22"
      }
     };
 
     type22Mapping.ItemMappings.Add(new ItemMapping
     {
      DataPointMember = DataPointMember.YValue,
      FieldName = "FixedCost"
     });
 
     type22Mapping.ItemMappings.Add(new ItemMapping
     {
      DataPointMember = DataPointMember.XCategory,
      FieldName = "DateTime"
     });
 
     type22Mapping.ItemMappings.Add(new ItemMapping
     {
      DataPointMember = DataPointMember.LegendLabel,
      FieldName = "Title"
     });
     _seriesMappings.Add(type22Mapping);
     
     
   }
 
   #endregion
 
   #region Type3 (bar)
   if (_currentCustomization.ShowType3)
   {
    if (_defaultYAxisName == null)
     _defaultYAxisName = "Type3";
 
    if (_defaultYAxis == null)
     _defaultYAxis = new AxisY
     {
      AxisName = "Type3",
      Title = "Type3"
     };
    else
     _yAxes.Add(new AxisY
     {
      AxisName = "Type3",
      Title = "Type3"
     });
 
    var type3Mapping = new SeriesMapping
      {
       CollectionIndex = _displayedConsumptionData.IndexOf(collection),
       LegendLabel = collection.FirstOrDefault().Title + " (Type3)",
       SeriesDefinition =
        new BarSeriesDefinition
         {
          ShowItemToolTips = AllValuesHidden,
          ShowItemLabels = !AllValuesHidden,
          AxisName = "Type3"
         }
      };
 
    type3Mapping.ItemMappings.Add(new ItemMapping
            {
             DataPointMember = DataPointMember.YValue,
             FieldName = "Type3"
            });
 
    type3Mapping.ItemMappings.Add(new ItemMapping
            {
             DataPointMember = DataPointMember.XCategory,
             FieldName = "DateTime"
            });
 
    type3Mapping.ItemMappings.Add(new ItemMapping
            {
             DataPointMember = DataPointMember.LegendLabel,
             FieldName = "Title"
            });
    _seriesMappings.Add(type3Mapping);
   }
 
   #endregion
  }
 
  if (_defaultYAxis != null)
   OnPropertyChanged("DefaultYAxis");
  OnPropertyChanged("YAxes");
  return _seriesMappings;
 }
}


DataObject (VM)
public class ConsumptionData
{
 public String Type { get; set; }
 public DateTime DateTime { get; set; }
 public Decimal Value { get; set; }
 public String Title { get; set; }
 public decimal VariableCost { get; set; }
 public decimal CO2 { get; set; }
}

Collection of data objects (VM)
private ObservableCollection<ObservableCollection<ConsumptionData>> _displayedConsumptionData;
public ObservableCollection<ObservableCollection<ConsumptionData>> DisplayedConsumptionData
{
 get
 {
  return _displayedConsumptionData ?? (_displayedConsumptionData = new ObservableCollection<ObservableCollection<ConsumptionData>>());
 }
 set
 {
  if (_displayedConsumptionData != value)
  {
   _displayedConsumptionData = value;
   OnPropertyChanged("DisplayedConsumptionData");
  }
 }
}

I've also tried exposing the RadChart to the ViewModel and instead of calling OnPropertyChanged("AxisY") setting the YAxis manually to the one which should be default (at the end of setting up the SeriesMappings)

View.Chart.DefaultView.ChartArea.AxisY = DefaultYAxis;

.. but the range is all wrong for the default series axis as can be seen in the screenshots I've attached.

Any idea to why this is happening? Where am I taking the wrong turn here?

2 Answers, 1 is accepted

Sort by
0
Missing User
answered on 24 Aug 2011, 03:18 PM
Hello Tobias Lolax,

RadChart always has a default YAxis that is linked to all series definitions. When you have additional YAxes you need to link each of them to the corresponding series via SeriesMapping.SeriesDefinition.AxisName property. If you leave this property empty, the series will use the default YAxis.
In your case, the number of the additional YAxes needs to be one less than the number of the series definitions. Therefore, the first created series will use the default YAxis and you will not need to set the default YAxis manually. For additional information on adding Multiple Y axes, please refer to the following online resources:
http://www.telerik.com/help/silverlight/radchart-features-axes-multiple-y-axes.html
http://demos.telerik.com/silverlight/#Chart/MultipleYAxes

I hope this information helps.

Best wishes,
Polina
the Telerik team

Thank you for being the most amazing .NET community! Your unfailing support is what helps us charge forward! We'd appreciate your vote for Telerik in this year's DevProConnections Awards. We are competing in mind-blowing 20 categories and every vote counts! VOTE for Telerik NOW >>

0
Tobias Rodewi
Top achievements
Rank 1
answered on 30 Aug 2011, 09:30 AM
Thanks Polina, the solution was as simple as I had hoped.
I previously set the AxisName to null for the one that should've been the default one (guess this should've been String.Empty instead), but this didn't work out, just not setting an AxisName at all sorted things out.
Tags
Chart
Asked by
Tobias Rodewi
Top achievements
Rank 1
Answers by
Missing User
Tobias Rodewi
Top achievements
Rank 1
Share this question
or