While OxyPlot continues to be one of the attractive plotting library for .Net developers, there are times when you find longing for features that could make it even more better.
One of such feature is ability to select/highlight a point in a series. While there is a Selectable Property with LineSeries, it doesn’t quite let you highlight the Data Point.
However, this can be easily achieved using another series with has a single point (the point which was selected). I guess it is easier to show the code than describe it. So let’s go ahead and hit Visual Studio.
We would begin by defining couple of Custom Series. For the sake of example, I am considering LineSeries in this case. The first Custom Series we would define would be the series which displays the Selected Item.
public class SelectedLineSeries:LineSeries { }
As you can observe, it hardly does anything new. The purpose of the definition is to allow is to easily differenciate between our special Series from Line Series. This would be further clarified when introduce our second custom series, which denotes a series which can be selected.
public class SelectableLineSeries:LineSeries { public bool IsDataPointSelectable { get; set; } public DataPoint CurrentSelection { get; set; } public OxyColor SelectedDataPointColor { get; set; } = OxyColors.Red; public double SelectedMarkerSize { get; set; } public SelectableLineSeries() { SelectedMarkerSize = MarkerSize; MouseDown += SelectableLineSeries_MouseDown; } private void SelectableLineSeries_MouseDown(object sender, OxyMouseDownEventArgs e) { if (IsDataPointSelectable) { var activeSeries = (sender as OxyPlot.Series.Series); var currentPlotModel = activeSeries.PlotModel; var nearestPoint = activeSeries.GetNearestPoint(e.Position, false); CurrentSelection = nearestPoint.DataPoint; currentPlotModel = ClearCurrentSelection(currentPlotModel); var selectedSeries = new SelectedLineSeries { MarkerSize = MarkerSize + 2, MarkerFill = SelectedDataPointColor, MarkerType = MarkerType }; selectedSeries.Points.Add(CurrentSelection); currentPlotModel.Series.Add(selectedSeries); currentPlotModel.InvalidatePlot(true); } } private PlotModel ClearCurrentSelection(PlotModel plotModel) { while(plotModel.Series.Any(x=> x is SelectedLineSeries)) { plotModel.Series.Remove(plotModel.Series.First(x=> x is SelectedLineSeries)); } return plotModel; } }
The core functionality of the Class is defined in the Series Mouse Down event. This ensures that whenever a point is selected, a new series is added to the Parent PlotModel, which has a single Data Point ( same as the currently selected data point).
Well, that’s all our definition is about. Now we can go ahead and define our PlotModel to be used along with Series definition.
var random = new Random(); var collection = Enumerable.Range(1, 5).Select(x => new DataPoint(x, random.Next(100, 400))).ToList(); var series = new SelectableLineSeries { IsDataPointSelectable = true, MarkerFill = OxyColors.Blue, MarkerType = MarkerType.Square, LineStyle = LineStyle.Solid, Color = OxyColors.Blue, ItemsSource = collection, MarkerSize = 5 }; GraphModel = new PlotModel(); GraphModel.Axes.Add(new OxyPlot.Axes.LinearAxis { Position = Axes.AxisPosition.Bottom }); GraphModel.Axes.Add(new OxyPlot.Axes.LinearAxis { Position = Axes.AxisPosition.Left }); GraphModel.Series.Add(series); GraphModel.InvalidatePlot(true);
That’s it. Hit F5 and test your Selectable Line Series. You can access the source code shown in the demo in my Github.