Multiple Axis with CategoricalSeriesDescriptor

12 posts, 1 answers
  1. Spimac
    Spimac avatar
    7 posts
    Member since:
    Jan 2013

    Posted 18 Oct 2013 Link to this post

    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.
  2. Spimac
    Spimac avatar
    7 posts
    Member since:
    Jan 2013

    Posted 22 Oct 2013 Link to this post

    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.
  3. DevCraft banner
  4. Answer
    Milena
    Admin
    Milena avatar
    204 posts

    Posted 23 Oct 2013 Link to this post

    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 >>
  5. Spimac
    Spimac avatar
    7 posts
    Member since:
    Jan 2013

    Posted 24 Oct 2013 Link to this post

    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.
  6. Milena
    Admin
    Milena avatar
    204 posts

    Posted 29 Oct 2013 Link to this post

    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 >>
  7. Nitin Nitin
    Nitin Nitin avatar
    41 posts
    Member since:
    Apr 2010

    Posted 15 Nov 2013 Link to this post

    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 
  8. Nitin Nitin
    Nitin Nitin avatar
    41 posts
    Member since:
    Apr 2010

    Posted 16 Nov 2013 Link to this post

    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
  9. Nitin Nitin
    Nitin Nitin avatar
    41 posts
    Member since:
    Apr 2010

    Posted 16 Nov 2013 Link to this post

    hello telerik,

    please reply to my query

  10. Yavor
    Admin
    Yavor avatar
    401 posts

    Posted 18 Nov 2013 Link to this post

    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 >>
  11. Nitin Nitin
    Nitin Nitin avatar
    41 posts
    Member since:
    Apr 2010

    Posted 20 Nov 2013 Link to this post

    Thanks for the solution.

    Best Regards,
    Nitin 
  12. E
    E avatar
    1 posts
    Member since:
    Apr 2014

    Posted 24 Apr 2014 in reply to Yavor Link to this post

                                <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.
  13. Martin
    Admin
    Martin avatar
    1101 posts

    Posted 28 Apr 2014 Link to this post

    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.
     
Back to Top
DevCraft banner