RadCartesianChart Series Click to MVVM Command with parameter

5 posts, 0 answers
  1. Doug
    Doug avatar
    7 posts
    Member since:
    Apr 2009

    Posted 18 Sep 2014 Link to this post

    I have a WPF MVVM application with a screen that has a Telerik Chart(RadCartesianChart) on it. The chart can contain more than one series in it. I need to have at least one of the series be clickable and based on the click execute a command in the View Model sending it the point (or at least the X axis) on the line that was clicked.

    I believe I need to set the Command and CommandParameter in the codebehind of the page, but not sure how.

    In the end I need the click command of the series to execute the PlotChartItemClickedCommand Sending it a parameter containing the X axis data which in my case is the Category.

    Below is my code XAML, CodeBehind and VM. Any help would be greatly appreciated

    XAML:
    <telerik:RadCartesianChart x:Name="RccLineChart"
                                  Width="354"
                                  Height="300" >
        <telerik:RadCartesianChart.Resources>
            <DataTemplate x:Key="PointTemplate">
                <Ellipse Height="6" Width="6" Fill="red" />
            </DataTemplate>
        </telerik:RadCartesianChart.Resources>
        <telerik:RadCartesianChart.HorizontalAxis>
            <telerik:CategoricalAxis ShowLabels="False" Title="Count" x:Name="LineHorzAxis"/>
        </telerik:RadCartesianChart.HorizontalAxis>
        <telerik:RadCartesianChart.VerticalAxis>
            <telerik:LinearAxis Maximum="{Binding Path=MaxYValue}" Minimum="{Binding Path=MinYValue}" Title="C"/>
        </telerik:RadCartesianChart.VerticalAxis>
        <telerik:RadCartesianChart.Series>
        </telerik:RadCartesianChart.Series>
    </telerik:RadCartesianChart>

    CodeBehind:
    public CodeBehindConstructor()
    {
        InitializeComponent();
        InitialIzeLineChart();
    }
     
    private void InitialIzeLineChart()
    {
        foreach (CartesianSeries series in GetSeries())
        {
            RccLineChart.Series.Add(series);
        }
    }
     
    private IEnumerable<CartesianSeries> GetSeries()
    {
        string Line1ItemsSourcePath = string.Empty;
        string PointsItemsSourcePath = string.Empty;
        string referenceLineItemsSourcePath = string.Empty;
        string Line1Resource = string.Empty;
        string PointsResource = string.Empty;
        Line1Resource = "Line1Template";
        PointsResource = "PointTemplate";
     
        CategoricalSeries Line1Series = null;
        CategoricalSeries PointSeries = null;
        CategoricalSeries referenceLineSeries = null;
        Line1Series = new LineSeries();
        PointSeries = new PointSeries();
        referenceLineSeries = new LineSeries();
     
        Line1ItemsSourcePath = "Line1Data";
        PointsItemsSourcePath = "PointsData";
        referenceLineItemsSourcePath = "ReferenceLine";
     
        List<CartesianSeries> generatedSeries = new List<CartesianSeries>();
        Line1Series.CategoryBinding = new PropertyNameDataPointBinding("Category");//this is what we want to send to the VM on the click of the chart
        Line1Series.ValueBinding = new PropertyNameDataPointBinding("Data");
        Line1Series.ShowLabels = false;
        Line1Series.CombineMode = ChartSeriesCombineMode.None;
        Line1Series.IsHitTestVisible = true;
        Line1Series.SetBinding(CategoricalSeries.ItemsSourceProperty, new Binding(Line1ItemsSourcePath));
        Line1Series.PointTemplate = this.Resources[Line1Resource] as DataTemplate;
     
        //CommandBinding lineCB = new CommandBinding();
        //ICommand lineCommand = new ICommand();
         
        generatedSeries.Add(Line1Series);
     
        PointSeries.CategoryBinding = new PropertyNameDataPointBinding("Category");
        PointSeries.ValueBinding = new PropertyNameDataPointBinding("Data");
        PointSeries.ShowLabels = true;
        PointSeries.CombineMode = ChartSeriesCombineMode.None;
        PointSeries.SetBinding(CategoricalSeries.ItemsSourceProperty, new Binding(PointsItemsSourcePath));
        PointSeries.PointTemplate = this.Resources[PointsResource] as DataTemplate;
     
        generatedSeries.Add(PointSeries);
     
        referenceLineSeries.CategoryBinding = new PropertyNameDataPointBinding("Category");
        referenceLineSeries.ValueBinding = new PropertyNameDataPointBinding("Data");
        referenceLineSeries.ShowLabels = false;
        referenceLineSeries.CombineMode = ChartSeriesCombineMode.None;
        referenceLineSeries.IsHitTestVisible = true;
        referenceLineSeries.SetBinding(CategoricalSeries.ItemsSourceProperty, new Binding(referenceLineItemsSourcePath));
        referenceLineSeries.PointTemplate = this.Resources[Line1Resource] as DataTemplate;
     
        generatedSeries.Add(referenceLineSeries);
     
        return generatedSeries;
    }

    ViewModel:
    public RelayCommand<ChartItemClickEventArgs> PlotChartItemClickedCommand
    {
        get { return new RelayCommand<ChartItemClickEventArgs>(PlotChartItemClickedExecute, AlwaysTrueCanExecute); }
    }
     
    private void ProfilePlotChartItemClickedExecute(object e)
    {
        int xPointClicked = ?????
     
    }



  2. kirk
    kirk avatar
    1 posts
    Member since:
    Sep 2014

    Posted 22 Sep 2014 in reply to Doug Link to this post

    I'm having the same problem, are there any solutions yet?
  3. UI for WPF is Visual Studio 2017 Ready
  4. Petar Marchev
    Admin
    Petar Marchev avatar
    968 posts

    Posted 23 Sep 2014 Link to this post

    Hello Doug,

    Depending on the exact behavior you want to get, you can use different approaches.

    From what I understand you have logic that needs to be executed when a Category of the axis is clicked. So perhaps this logic needs to be executed when the reader clicks an axis label and not a data point visual. So do consider executing this code when an axis label gets clicked.

    Whether you decide to make the axis label clickable or the data point clickable - you can use a style and an attached behavior to get this. Say that you are using BarSeries - you need to use a DefaultVisualStyle that has a setter for a custom attached property. In the attached property you can attach handlers for the mouse up and down events. In the handlers you can find the DataContext of the visual element (it is a DataPoint) and from the data point you can get the data-item and the parenting series and chart, so you can get the view model and call the method you need. I hope this helps.

    Regards,
    Petar Marchev
    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.
     
  5. Doug
    Doug avatar
    7 posts
    Member since:
    Apr 2009

    Posted 23 Sep 2014 in reply to Petar Marchev Link to this post

    Petar,

    I do need the click point of the line. In addition, I may have more than one line in the chart, so I will need to execute a different command depending on which line in the chart is clicked. That is the reason why I was thinking that the code I am needing would need to go in the codebehind as the LineSeries is being defined. Am I thinking correctly? In either case do you have a code sample I could see?

    Thanks,

    Doug
  6. Petar Marchev
    Admin
    Petar Marchev avatar
    968 posts

    Posted 25 Sep 2014 Link to this post

    Hi Doug,

    If the line series has a point template - you could make the points clickable. Do you have points or is it just a line?

    If you have points - you can use the approach described earlier, a style with a setter for an attached property (you can define the style in code).

    If you do not have points - there is nothing to be clicked and you can simply attach a handler to the MouseDown event of the line series and execute the logic per series, not per data point (because there are no data point visuals).

    If you need further assistance please send us some snapshots of the current output and explanations where you would like to click the series and what information do you need in the click handler - the data point or the series.

    Regards,
    Petar Marchev
    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
UI for WPF is Visual Studio 2017 Ready