0

I'm implementing a little app with Xamarin Forms for a web page, the thing is that in this web is a linear chart with multiple entries and if the user clicks on a point of the line shows info about that point, as you can see in the picture:

Web Line Chart

After some work, I could create a more or less similar line chart using the OxyPlot.Xamarin.Forms plugin with multiple entries which shows the points

My App Line Chart

This is my code:

        OnPropertyChanged("GraphModel");

        var model = new PlotModel
        {
            LegendPlacement = LegendPlacement.Outside,
            LegendPosition = LegendPosition.BottomCenter,
            LegendOrientation = LegendOrientation.Horizontal,
            LegendBorderThickness = 0
        };
        model.PlotType = PlotType.XY;
        model.InvalidatePlot(false);

        Dictionary<string, List<Prices>> values = HistoricData[Selected.ProductId];

        int colorIndex = 0;
        List<string> x_names = new List<string>();

        foreach (var item in values.Keys)
        {

            if (item.ToUpper() == Selected.ProductName) { SelectedIndex = colorIndex; }
            var lineSeries = new LineSeries()
            {
                Title = item,
                MarkerType = MarkerType.Circle,
            };
            lineSeries.MarkerResolution = 3;
            lineSeries.MarkerFill = OxyPlot.OxyColor.Parse(SubCategoriesViewModel.AvailableColors[colorIndex]);
            lineSeries.MarkerStroke = OxyPlot.OxyColor.Parse(SubCategoriesViewModel.AvailableColors[colorIndex]);
            lineSeries.MarkerSize = 3;

            var points = new List<DataPoint>();


            lineSeries.Color = OxyColor.Parse(SubCategoriesViewModel.AvailableColors[colorIndex]);

            foreach (var price in values[item])
            {
                points.Add(new DataPoint(price.Week+price.Year, price.Price));

            }

            if (ButtonsVisibility.Count == 0)
            {
                lineSeries.IsVisible = (Selected.ProductName == item.ToUpper()) ? true : false;
            }
            else
            {
                lineSeries.IsVisible = ButtonsVisibility[colorIndex];
            }


            lineSeries.ItemsSource = points;
            lineSeries.MarkerType = OxyPlot.MarkerType.Circle;
            model.Series.Add(lineSeries);
            colorIndex++;
        }

        NumButtons = colorIndex;
        LinearAxis yaxis = new LinearAxis();
        yaxis.Position = AxisPosition.Left;
        yaxis.MajorGridlineStyle = LineStyle.Dot;
        model.Axes.Add(yaxis);

        LineChart = model;
        OnPropertyChanged("GraphModel");
        return LineChart;

My doubt is which property I should work with and show at least the value of a concrete point, I have seen the property OnTouchStarted but is only for all the LineSeries and not for a single point. I read in some articles that OxyPlot.Xamarin.Forms include a tracker. I added this line in my code:

lineSeries.TrackerFormatString = "X={2},\nY={4}";

Is supposed to show the x and y values on click but doesn't show anything, any suggestion? Should show something like that: Tracker info on point

From the following example: Tracker Example

Updated Code

public PlotModel GetLineChart()
{
    OnPropertyChanged("GraphModel");

    var model = new PlotModel
    {
        LegendPlacement = LegendPlacement.Outside,
        LegendPosition = LegendPosition.BottomCenter,
        LegendOrientation = LegendOrientation.Horizontal,
        LegendBorderThickness = 0
    };
    model.PlotType = PlotType.XY;
    model.InvalidatePlot(false);

    Dictionary<string, List<Prices>> values = HistoricData[Selected.ProductId];

    int colorIndex = 0;
    List<string> x_names = new List<string>();

    foreach (var item in values.Keys)
    {

        if (item.ToUpper() == Selected.ProductName) { SelectedIndex = colorIndex; }
        var lineSeries = new LineSeries()
        {
            Title = item,
            MarkerType = MarkerType.Circle,
            CanTrackerInterpolatePoints = false

        };
        lineSeries.MarkerResolution = 3;
        lineSeries.MarkerFill = OxyPlot.OxyColor.Parse(SubCategoriesViewModel.AvailableColors[colorIndex]);
        lineSeries.MarkerStroke = OxyPlot.OxyColor.Parse(SubCategoriesViewModel.AvailableColors[colorIndex]);
        lineSeries.MarkerSize = 3;

        var points = new List<DataPoint>();


        lineSeries.Color = OxyColor.Parse(SubCategoriesViewModel.AvailableColors[colorIndex]);

        foreach (var price in values[item])
        {
           points.Add(new DataPoint(price.Week+price.Year, price.Price)); 
        }

        if (ButtonsVisibility.Count == 0)
        {
            lineSeries.IsVisible = (Selected.ProductName == item.ToUpper()) ? true : false;
        }
        else
        {
            lineSeries.IsVisible = ButtonsVisibility[colorIndex];
        }


        lineSeries.ItemsSource = points;
        lineSeries.MarkerType = OxyPlot.MarkerType.Circle;

        lineSeries.TrackerFormatString = "X={2},\nY={4}";

        lineSeries.TextColor = OxyPlot.OxyColor.Parse(SubCategoriesViewModel.AvailableColors[colorIndex]);
        model.Series.Add(lineSeries);
        colorIndex++;
    }

    NumButtons = colorIndex;

    LinearAxis yaxis = new LinearAxis();
    yaxis.Position = AxisPosition.Left;
    //yaxis.StringFormat = "X={2},\nY={4}";
    yaxis.MajorGridlineStyle = LineStyle.Dot;
    model.Axes.Add(yaxis);

    LineChart = model;
    OnPropertyChanged("GraphModel");
    return LineChart;

}

}

 protected async override void OnAppearing()
        {
            await _viewModel.LinearViewModel.GetSubCategoryHistoricWeekPrices(App.ViewModel.LoginViewModel.SesionToken, FROM_DATE, TO_DATE);
            Plot.Model = _viewModel.LinearViewModel.GetLineChart();
            PlotController controller = new PlotController();
            controller.UnbindAll();
            controller.BindTouchDown(PlotCommands.PointsOnlyTrackTouch);
            Plot.Controller = controller;



            AddButtons();


        }

Xaml Declaration for plot view:

<oxy:PlotView 
            Grid.Row="2"
            Grid.RowSpan="2"
            Grid.ColumnSpan="4"            
            x:Name="Plot" />
notarealgreal
  • 734
  • 16
  • 29

1 Answers1

2

Your problem lies with following line.

lineSeries.TrackerKey = "X={2},\nY={4}";

When you use series.TrackerKey, you are specifying that you are using a CustomTracker, which in this case you are not. Custom trackers would be useful if you need to use different trackers for each series in the model.

In you case, you should remove that line and use only TrackerFormatString.

lineSeries.TrackerFormatString = "X={2},\nY={4}";

This would show the tooltip using the format string parameters, where {2} signifies X Value and {4} signifies Y. For your information, following are place holders.

{0} = Title of Series
{1} = Title of X-Axis
{2} = X Value
{3} = Title of Y-Axis
{4} = Y Value

If you need to include additional/custom information in your tool, your Data Point needs to be include that information. This where IDataPointProvider interface becomes handy. You could create a Custom DataPoint by implementing the interface and then you could include the same information in your tooltip as well.

Update Based On Comments

Additionally, to include "Touch", you can specify TouchDown in the PlotController. You can do so by defining the PlotController in your viewModel as following.

public PlotController CustomPlotController{get;set;}

You can define the property as follows.

CustomPlotController = new PlotController();
CustomPlotController.UnbindAll();
CustomPlotController.BindTouchDown(PlotCommands.PointsOnlyTrackTouch);

And in your Xaml

<oxy:Plot Controller="{Binding CustomPlotController}"......
Anu Viswan
  • 17,797
  • 2
  • 22
  • 51
  • I tried in different ways, following the article example my problem is that using only the TrackerFormatString parameter showing the x and y values only when I run the app after tabbing on a point still not appearing the tracker – notarealgreal Jan 29 '19 at 14:46
  • Sorry, but it is still unclear what your meant. Where exactly are you facing the issues ? You are not getting a tooltip at all or it shows up only on mouse click and you want to show it in MouseOver ? – Anu Viswan Jan 29 '19 at 14:52
  • The tooltip isn't shown anywhere when I click on a point, what I want is after a click/tap of the user, the Track to be shown like in the Tracker info on a point image – notarealgreal Jan 29 '19 at 14:53
  • Did you try removing this line of code "lineSeries.TrackerKey = "X={2},\nY={4}";" ? – Anu Viswan Jan 29 '19 at 14:54
  • Yes, I tried it only with the following line : "lineSeries.TrackerFormatString = "X={2},\nY={4}";" – notarealgreal Jan 29 '19 at 14:56
  • @notarealgreal I have updated the answer, could you try now – Anu Viswan Jan 29 '19 at 15:24
  • thank you for the suggestion but the tooltip still not appearing after a touch on a plot point. My doubt is, I'm using OxiPlot.Xamarin.Forms to show the plot on a mobile device, why did you suggest me "CustomPlotController.BindMouseDown(OxyMouseButton.Left,PlotCommands.PointsOnlyTrack);", OxyMouseButton.Left isn't there on tap or something similar? Because with these bindings for the controller doesn't work. – notarealgreal Jan 29 '19 at 16:52
  • You can remove the MouseDown. That is my mistake. I have updated the answer. Btw, it still doesn't work for you ? – Anu Viswan Jan 29 '19 at 16:53
  • @notarealgreal could you share your updated code in OP under a heading "Updated Code" ? – Anu Viswan Jan 30 '19 at 11:07
  • done, thank for your help I still thinking that the problem is that I cannot detect any click/tap event on the plot – notarealgreal Jan 30 '19 at 11:19