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

Multiple Axis with CategoricalSeriesDescriptor

11 Answers 367 Views
ChartView
This is a migrated thread and some comments may be shown as answers.
Spimac
Top achievements
Rank 1
Spimac asked on 18 Oct 2013, 02:53 PM
Hello,

I am using a RadCartesianChart with the lastest release (Q3 2013) and i have successfully poopulated my chart based on your example "Dynamic Number of Series (ChartSeriesProvider)".

I have a random number of series and i need to see the VerticalAxis of each series, right now all the series are bound to the main chart axis.

I tried using the following code:

<telerik:RadCartesianChart x:Name="chart" Grid.Column="0" Grid.Row="0" Zoom="3, 1">
 
<telerik:RadCartesianChart.HorizontalAxis>
            <telerik:DateTimeContinuousAxis x:Name="xAxis" PlotMode="OnTicks" MaximumTicks="10"  MajorStepUnit="Hour" FontSize="9">
              <telerik:DateTimeContinuousAxis.LabelTemplate>
                <DataTemplate>
                  <StackPanel>
                    <TextBlock Text="{Binding StringFormat=yyyy-MM-dd}" HorizontalAlignment="Center" />
                    <TextBlock Text="{Binding StringFormat=HH:mm}" HorizontalAlignment="Center" />
                  </StackPanel>
                </DataTemplate>
              </telerik:DateTimeContinuousAxis.LabelTemplate>
 
            </telerik:DateTimeContinuousAxis>
          </telerik:RadCartesianChart.HorizontalAxis>
 
          <telerik:RadCartesianChart.VerticalAxis>
            <telerik:LinearAxis x:Name="yAxisChart" Minimum="0" Maximum="100" MajorStep="20" Title="%" />
          </telerik:RadCartesianChart.VerticalAxis>
 
<telerik:RadCartesianChart.SeriesProvider>
            <telerik:ChartSeriesProvider Source="{Binding ValoresGrafico}">
              <telerik:ChartSeriesProvider.SeriesDescriptors>
 
                <telerik:CategoricalSeriesDescriptor ItemsSourcePath="ValoresGrafico" ValuePath="ValCorrigido" CategoryPath="Data">
                  <telerik:CategoricalSeriesDescriptor.Style>
                    <Style TargetType="telerik:LineSeries">
                      <Setter Property="Stroke" Value="{Binding SeriesBrush}"/>
                      <Setter Property="RenderMode" Value="Light"></Setter>
                      <Setter Property="Name" Value="{Binding Index}"></Setter>
                      <Setter Property="Tag" Value="{Binding Index}"></Setter>
                      <Setter Property="VerticalAxis">
                        <Setter.Value>
                          <telerik:LinearAxis ElementBrush="{Binding SeriesBrush}"></telerik:LinearAxis>
                        </Setter.Value>
                      </Setter>
                    </Style>                                       
                  </telerik:CategoricalSeriesDescriptor.Style>
                </telerik:CategoricalSeriesDescriptor>
                 
              </telerik:ChartSeriesProvider.SeriesDescriptors>
            </telerik:ChartSeriesProvider>               
          </telerik:RadCartesianChart.SeriesProvider>
 
</telerik:RadCartesianChart>

My base model class if the following:

public class GraficoInfo
  {
    public int Index { get; set; }
    public RadObservableCollection<PropriedadesGrafico> ValoresGrafico { get; set; }
    public Brush SeriesBrush { get; set; }
  }

When i have the setter property VerticalAxis in CategoricalSeriesDescriptor.Style i get the following error:

"Exception has been thrown by the target of an invocation." The message i get from the InnerException is "Element is already the child of another element".

Is it possible to associate multiple series to multiple axis with this approach with MVVM?

Best regards.

11 Answers, 1 is accepted

Sort by
0
Spimac
Top achievements
Rank 1
answered on 22 Oct 2013, 01:22 PM
I figured it out by adding an LinearAxis property to my base class and then binding the VerticalAxis setter to that property.

Now im trying to do the same with the Visibility property of the series. I have added another property to the class and have binded it to the Visibility setter. This works fine on the chart load but i want to change it based on user interaction.

I have a checkbox event that that triggers a method on my model class:

(chart.DataContext as GraficosViewModel).SetVisibility(0, false);

public void SetAxisVisibility(int t, bool p)
{
  if (p)
  {
    this.Valores[t].YAxis.Visibility = Visibility.Visible;
  }
  else
  {
    this.Valores[t].YAxis.Visibility = Visibility.Collapsed;
  }
}

but the visibility of the series never changes.

Am i missing something here?

Any help would be very appreciated.
0
Accepted
Milena
Telerik team
answered on 23 Oct 2013, 02:09 PM
Hi Paulo,

I'm sending you a sample project where you can see how to implement changing the Visibility of the series through binding in a MVVM friendly manner.

In your xaml code all you have to do is to write:

<Style TargetType="telerik:BarSeries">                                 
    <Setter Property="Visibility" Value="{Binding IsVisible, Converter={StaticResource BooleanToVisibilityConverter}}"/>
</Style>

I hope this information will help you and don't hesitate to write back if you have more questions.

Regards, Milena
Telerik
TRY TELERIK'S NEWEST PRODUCT - EQATEC APPLICATION ANALYTICS for SILVERLIGHT.
Learn what features your users use (or don't use) in your application. Know your audience. Target it better. Develop wisely.
Sign up for Free application insights >>
0
Spimac
Top achievements
Rank 1
answered on 24 Oct 2013, 04:23 PM
Hello again,

Thank you for your sample, it was most helpful.

I have another questions... we need to have a chart with a very large number of points and i would like to know if it is possible to use sampling with the ChartSeriesProvider form of populating data.

I see on your Q3 2013 release note that you have "Implemented native integration between ChartSeriesProvider and ChartDataSource"

What does this mean exactly? Is it possible to use ChartDataSource as source for ChartSeriesProvider?

Thank you again.
0
Milena
Telerik team
answered on 29 Oct 2013, 07:01 PM
Hello Paulo,

I'm glad that we have helped you to find a solution of your issue.

About your question regarding sampling - indeed we have implemented integration between ChartSeriesProvider and ChartDataSource. To enable it you need to use the ChartDataSourceStyle property of the CategoricalSeriesDescriptor. For example, in the project I have sent you should add:

<telerik:CategoricalSeriesDescriptor.ChartDataSourceStyle>
    <Style TargetType="telerik:ChartDataSource">
         <Setter Property="SamplingThreshold" Value="2" />
     </Style>
</telerik:CategoricalSeriesDescriptor.ChartDataSourceStyle>

The ChartDataSource settings will be applied to each series individually. So instead of getting N data points in each series, you will get N / SamplingThreshold. In sample project each of the 3 series has 4 data points. After applying the ChartDataSourceStyle you will get two for each series - the first being the average 0th and 1st and the second - of the 2nd and the 3rd.

I hope this information helps you. Don't hesitate to write back if you have more questions.

Regards,

Milena
Telerik
TRY TELERIK'S NEWEST PRODUCT - EQATEC APPLICATION ANALYTICS for SILVERLIGHT.
Learn what features your users use (or don't use) in your application. Know your audience. Target it better. Develop wisely.
Sign up for Free application insights >>
0
Nitin Nitin
Top achievements
Rank 1
answered on 15 Nov 2013, 01:57 PM
Hi there,

I have similar issue regarding vertical axis.

I need to show 2 vertical axis for dynamic series using mvvm which lies on the right and left hand side.
Also it should have title for those axis

Can you please provide me an example of the same.

It is very urgent.

Thanks,
Nitin 
0
Nitin Nitin
Top achievements
Rank 1
answered on 16 Nov 2013, 08:42 AM
I have tried the following but no luck in achieving to show 2 y-axis on the right hand side and left hand side with titles:

 
<telerik:RadCartesianChart.SeriesProvider>
           <telerik:ChartSeriesProvider Source="{Binding SeriesCollection,Mode=TwoWay}">
               <telerik:ChartSeriesProvider.SeriesDescriptors>
                   <telerik:CategoricalSeriesDescriptor ItemsSourcePath="Data" ValuePath="LineSeriesChartValue" CategoryPath="LineSeriesChartCategory">
                       <telerik:CategoricalSeriesDescriptor.Style>
                           <Style TargetType="telerik:LineSeries">
                               <Setter Property="CombineMode" Value="Cluster" />
                               <Setter Property="TrackBallInfoTemplate" Value="{Binding TrackballInfoTemplate, Mode=TwoWay}" />
                               <Setter Property="Stroke" Value="{Binding SeriesStroke, Mode=TwoWay}" />
                               <Setter Property="Tag" Value="{Binding SeriesName, Mode=TwoWay}" />
                               <Setter Property="VerticalAxis" Value="{Binding VerticalAxis, Mode=TwoWay}" />
                           </Style>
                       </telerik:CategoricalSeriesDescriptor.Style>
                   </telerik:CategoricalSeriesDescriptor>
               </telerik:ChartSeriesProvider.SeriesDescriptors>
           </telerik:ChartSeriesProvider>
        </telerik:RadCartesianChart.SeriesProvider>

and then in the viewmodel.cs:

ChartVM.SeriesResult[0].VerticalAxis = GetVerticalAxis(Telerik.Charting.AxisHorizontalLocation.Left, "Axis Title", "StyleName");
ChartVM.SeriesResult[1].VerticalAxis = GetVerticalAxis(Telerik.Charting.AxisHorizontalLocation.Left, "Axis Title", "StyleName");

 
private LinearAxis GetVerticalAxis(Telerik.Charting.AxisHorizontalLocation horizontalLocation, string title, string styleName)
        {
            LinearAxis verticalAxis = new LinearAxis();
            verticalAxis.HorizontalLocation = horizontalLocation;
            verticalAxis.Title = title;
            verticalAxis.Minimum = 0;
            verticalAxis.LineThickness = 0;
            verticalAxis.LabelTemplate = GetVerticalAxisLabelTemplate(horizontalLocation);
 
            if (horizontalLocation == Telerik.Charting.AxisHorizontalLocation.Left)
            {
                verticalAxis.Margin = new Thickness(0, 0, 0, 0);
               verticalAxis.TitleTemplate = CreateLeftYAxisDataTemplate(styleName, title);
            }
            else
            {
                verticalAxis.Margin = new Thickness(0, 0, 25, 0);
               verticalAxis.TitleTemplate = CreateRightYAxisDataTemplate(styleName, title);
            }
             
            return verticalAxis;
        }
 
private DataTemplate GetVerticalAxisLabelTemplate(Telerik.Charting.AxisHorizontalLocation horizontalLocation)
        {
            StringBuilder dtString = new StringBuilder();
            dtString.Append("<DataTemplate xmlns=\"http://schemas.microsoft.com/client/2007\">");
            dtString.Append("<Border  BorderThickness=\"0\">");
            if (horizontalLocation == Telerik.Charting.AxisHorizontalLocation.Left)
                dtString.Append("<TextBlock  Margin=\"25,0,0,0\" HorizontalAlignment=\"Right\" Text=\"{Binding }\" Style=\"{StaticResource AxisLabelTemplate}\"/>");
            else
                dtString.Append("<TextBlock  Margin=\"0,0,22,0\" HorizontalAlignment=\"Right\" Text=\"{Binding }\" Style=\"{StaticResource AxisLabelTemplate}\"/>");
             
            dtString.Append("</Border>");
            dtString.Append("</DataTemplate>");
            return (DataTemplate)System.Windows.Markup.XamlReader.Load(dtString.ToString());
        }

public DataTemplate CreateLeftYAxisDataTemplate(string applyStyle, string title)
        {
            StringBuilder dtString = new StringBuilder();
            dtString.Append("<DataTemplate xmlns=\"http://schemas.microsoft.com/client/2007\">");
            dtString.Append("<TextBlock  Margin=\"-65,-20,0,0\" HorizontalAlignment=\"Left\" VerticalAlignment=\"Top\" Text=\"" + title + "\" FontSize=\"{Binding Source={StaticResource  FontSize12}, Converter={StaticResource AppConverter}}\" Foreground=\"{StaticResource " + applyStyle + "}\"/>");
            dtString.Append("</DataTemplate>");
            return (DataTemplate)System.Windows.Markup.XamlReader.Load(dtString.ToString());
        }

        public DataTemplate CreateRightYAxisDataTemplate(string applyStyle, string title)
        {
            StringBuilder dtString = new StringBuilder();
            dtString.Append("<DataTemplate xmlns=\"http://schemas.microsoft.com/client/2007\">");
            dtString.Append("<TextBlock  Margin=\"-65,0,0,0\" HorizontalAlignment=\"Left\" VerticalAlignment=\"Top\" FontSize=\"{Binding Source={StaticResource  FontSize12}, Converter={StaticResource AppConverter}}\" Text=\"" + title + "\" Foreground=\"{StaticResource " + applyStyle + "}\"/>");
            dtString.Append("</DataTemplate>");
            return (DataTemplate)System.Windows.Markup.XamlReader.Load(dtString.ToString());
        }

and the Series ViewModel Class :
public class SeriesViewModel : BaseViewModel
    {
        private ObservableCollection<LineSeriesChartData> _Data;
        public ObservableCollection<LineSeriesChartData> Data
        {
            get { return _Data; }
            set { _Data = value; RaiseNotification("Data"); }
        }
 
        private DataTemplate m_TrackballInfoTemplate;
        public DataTemplate TrackballInfoTemplate
        {
            get { return m_TrackballInfoTemplate; }
            set
            {
                m_TrackballInfoTemplate = value;
                RaiseNotification("TrackballInfoTemplate");
            }
        }
 
        private SolidColorBrush m_SeriesStroke;
        public SolidColorBrush SeriesStroke
        {
            get { return m_SeriesStroke; }
            set
            {
                m_SeriesStroke = value;
                RaiseNotification("SeriesStroke");
            }
        }
 
        private string m_SeriesName;
        public string SeriesName
        {
            get { return m_SeriesName; }
            set
            {
                m_SeriesName = value;
                RaiseNotification("SeriesName");
            }
        }
 
        private DataTemplate m_SeriesTitleTemplate;
        public DataTemplate SeriesTitleTemplate
        {
            get { return m_SeriesTitleTemplate; }
            set
            {
                m_SeriesTitleTemplate = value;
                RaiseNotification("SeriesTitleTemplate");
            }
        }
 
        private LinearAxis m_VerticalAxis;
        public LinearAxis VerticalAxis
        {
            get { return m_VerticalAxis; }
            set
            {
                m_VerticalAxis = value;
                RaiseNotification("VerticalAxis");
            }
        }
 
        
        public SeriesViewModel()
        {
            this.Data = new ObservableCollection<LineSeriesChartData>();
        }
         
    }

No luck with the above implementation.

I'm trying to show 2 vertical axis with titles of each one, but unable to do it.

Can you please help or send me a solution showing the implementation asap.

Thanks,
Nitin Nitin
0
Nitin Nitin
Top achievements
Rank 1
answered on 16 Nov 2013, 10:02 AM
hello telerik,

please reply to my query

0
Yavor
Telerik team
answered on 18 Nov 2013, 03:27 PM
Hello Nitin,

Please check the attached project. I have prepared it for you to show you how you can bind and axis to view model using the series provider.

Hope this helps!

Regards,
Yavor
Telerik
TRY TELERIK'S NEWEST PRODUCT - EQATEC APPLICATION ANALYTICS for SILVERLIGHT.
Learn what features your users use (or don't use) in your application. Know your audience. Target it better. Develop wisely.
Sign up for Free application insights >>
0
Nitin Nitin
Top achievements
Rank 1
answered on 20 Nov 2013, 07:22 AM
Thanks for the solution.

Best Regards,
Nitin 
0
E
Top achievements
Rank 1
answered on 24 Apr 2014, 05:56 AM
                            <telerik:CategoricalSeriesDescriptor.Style>
                                <Style TargetType="telerik:LineSeries">
                                    <Setter Property="StrokeThickness" Value="1"/>
                                    <Setter Property="Visibility" Value="{Binding Name , Converter={StaticResource pointFocusConverter}}"/>
                                    <Setter Property="LegendSettings">
                                        <Setter.Value>
                                            <telerik:SeriesLegendSettings Title="{Binding Name}"/>
                                        </Setter.Value>
                                    </Setter>
                                    <Setter Property="VerticalAxis">
                                        <Setter.Value>
                                            <telerik:LinearAxis ElementBrush="White" />
                                        </Setter.Value>
                                    </Setter>
                                </Style>
                            </telerik:CategoricalSeriesDescriptor.Style>

It's my XAML code but I want's to do.

I want to work making vertical axis each series.

but this code is making one series.

My series is decided dynamically.

Please help me.
0
Martin Ivanov
Telerik team
answered on 28 Apr 2014, 04:19 PM
Hi,

When you set the VerticalAxis like in the provided code snippet you create a single axis and share it with all series which uses the style. In order to achieve your requirement you can use few approaches. You can use an IValueConverter which will create a new axis for each series.
<Setter Property="VerticalAxis" Value="{Binding Converter={StaticResource VerticalAxisConverter}}" />
...
public class VerticalAxisConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        return new LinearAxis();
    }
    .....
}

Another option could be to create a property of type LinearAxis in your business class which holds the series and then bind this property to the VerticalAxis in the Style's Setter.
<Setter Property="VerticalAxis" Value="{Binding VerticalAxis}" />

You can also create an attached property and set the new Axis in the  OnPropertyChangedCallback of this property.

However, if you have any other questions please ask them in a new forum thread. This will make our communication easier.

Regards,
Martin
Telerik
 
Check out Telerik Analytics, the service which allows developers to discover app usage patterns, analyze user data, log exceptions, solve problems and profile application performance at run time. Watch the videos and start improving your app based on facts, not hunches.
 
Tags
ChartView
Asked by
Spimac
Top achievements
Rank 1
Answers by
Spimac
Top achievements
Rank 1
Milena
Telerik team
Nitin Nitin
Top achievements
Rank 1
Yavor
Telerik team
E
Top achievements
Rank 1
Martin Ivanov
Telerik team
Share this question
or