Skip to content

Commit 5a68d29

Browse files
authored
Merge pull request #720 from telerik/dkrastev/m-KB
KB-ChartView closest data point
2 parents afa3e37 + 327ef4b commit 5a68d29

File tree

3 files changed

+249
-0
lines changed

3 files changed

+249
-0
lines changed
Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
---
2+
title: Finding the Nearest ScatterDataPoint to a Mouse Click in RadChartView
3+
description: Learn how to determine the closest ScatterDataPoint in a RadChartView when the user clicks within the chart area.
4+
type: how-to
5+
page_title: How to Identify the Closest ScatterDataPoint to a Mouse Click in RadChartView
6+
slug: chartview-scatterseries-closest-point-mouseclick
7+
tags: radchartview, scatterdatapoint, winforms, mouseeventargs, chart-axes
8+
res_type: kb
9+
ticketid: 1686235
10+
---
11+
12+
## Environment
13+
14+
|Product Version|Product|Author|
15+
|----|----|----|
16+
|2025.1.211|RadChartView for WinForms|[Dinko Krastev](https://www.telerik.com/blogs/author/dinko-krastev)|
17+
18+
## Description
19+
20+
This article will demonstrate how to determine the nearest ScatterDataPoint to a mouse click location using the mouse click position.
21+
22+
![WinForms RadChartView ClosestDataPoint](images/chartView-closestdatapoint.png)
23+
24+
## Solution
25+
26+
To achieve this, calculate the axis values corresponding to the mouse click position on the chart. Then iterate over the data points in the series and determine the closest one.
27+
28+
Once the closest point is identified, you can create an additional ScatterSeries and add a duplicate ScatterDataPoint with the same values. This secondary series can be used to visually highlight the nearest data point.
29+
30+
The following code snippet demonstrates a full implementation.
31+
32+
````C#
33+
public partial class Form1 : Form
34+
{
35+
ScatterSeries scatterSeries = new ScatterSeries();
36+
public Form1()
37+
{
38+
InitializeComponent();
39+
scatterSeries.Name = "";
40+
scatterSeries.DataPoints.Add(new ScatterDataPoint(19000, 15));
41+
scatterSeries.DataPoints.Add(new ScatterDataPoint(10000, 18));
42+
scatterSeries.DataPoints.Add(new ScatterDataPoint(15000, 13));
43+
scatterSeries.DataPoints.Add(new ScatterDataPoint(80000, 10));
44+
scatterSeries.DataPoints.Add(new ScatterDataPoint(60000, 25));
45+
scatterSeries.PointSize = new SizeF(5, 5);
46+
this.radChartView1.Series.Add(scatterSeries);
47+
48+
this.radChartView1.MouseDown += RadChartView1_MouseDown;
49+
}
50+
private void RadChartView1_MouseDown(object sender, MouseEventArgs e)
51+
{
52+
Point pt = this.radChartView1.ChartElement.Wrapper.PointFromControl(e.Location);
53+
double verticalValue = Convert.ToDouble(GetVerticalAxisValueFromMouse(e));
54+
double horizontalValue = Convert.ToDouble(GetHorizontalAxisValueFromMouse(e));
55+
56+
Debug.WriteLine("X: " + horizontalValue + " Y: " + verticalValue);
57+
58+
ScatterDataPoint closestPoint = null;
59+
double minDistance = double.MaxValue;
60+
61+
var seriesToRemove = this.radChartView1.Series.FirstOrDefault(s => s.Name =="Closest Point");
62+
if (seriesToRemove != null)
63+
{
64+
this.radChartView1.Series.Remove(seriesToRemove);
65+
}
66+
foreach (ScatterDataPoint dataPoint in scatterSeries.DataPoints)
67+
{
68+
// Calculate the Euclidean distance
69+
double distance = Math.Sqrt(Math.Pow(dataPoint.XValue - horizontalValue, 2) + Math.Pow((double)dataPoint.YValue - verticalValue, 2));
70+
// Update the closest point if the current distance is smaller
71+
if (distance < minDistance)
72+
{
73+
minDistance = distance;
74+
closestPoint = dataPoint;
75+
}
76+
}
77+
78+
if (closestPoint != null)
79+
{
80+
var newScatterSeries = new ScatterSeries();
81+
newScatterSeries.Name = "Closest Point";
82+
newScatterSeries.DataPoints.Add(new ScatterDataPoint(closestPoint.XValue, (double)closestPoint.YValue));
83+
newScatterSeries.PointSize = new SizeF(15, 15);
84+
newScatterSeries.BorderColor = Color.Red;
85+
this.radChartView1.Series.Add(newScatterSeries);
86+
this.radChartView1.Invalidate();
87+
this.radChartView1.Update();
88+
}
89+
}
90+
91+
private object GetHorizontalAxisValueFromMouse(MouseEventArgs e)
92+
{
93+
LinearAxis axis = radChartView1.Axes[0] as LinearAxis;
94+
IChartView view = (IChartView)axis.View;
95+
double delta = axis.ActualRange.Maximum - axis.ActualRange.Minimum;
96+
double totalWidth = axis.Model.LayoutSlot.Width;
97+
double ratio = 1 - (e.Location.X - this.radChartView1.Area.View.Viewport.X - view.PlotOriginX - axis.Model.LayoutSlot.X) / (totalWidth * view.ZoomWidth);
98+
double value = axis.ActualRange.Minimum + delta * ratio;
99+
return axis.ActualRange.Maximum - value;
100+
}
101+
private object GetVerticalAxisValueFromMouse(MouseEventArgs e)
102+
{
103+
LinearAxis axis = radChartView1.Axes[1] as LinearAxis;
104+
IChartView view = (IChartView)axis.View;
105+
double delta = axis.ActualRange.Maximum - axis.ActualRange.Minimum;
106+
double totalHeight = axis.Model.LayoutSlot.Height;
107+
double ratio = 1 - (e.Location.Y - this.radChartView1.Area.View.Viewport.Y - view.PlotOriginY - axis.Model.LayoutSlot.Y) / (totalHeight * view.ZoomHeight);
108+
double value = axis.ActualRange.Minimum + delta * ratio;
109+
return value;
110+
}
111+
}
112+
113+
````
114+
115+
## See Also
116+
117+
- [RadChartView Overview Documentation](https://docs.telerik.com/devtools/winforms/controls/chartview/overview)
5.04 KB
Loading
Lines changed: 132 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,132 @@
1+
---
2+
title: Highlight the Last Selected Menu Item In RadMenu
3+
description: Learn how to keep selected menu items highlighted in RadMenu for WinForms by implementing custom code.
4+
type: how-to
5+
page_title: Highlighting Selected Menu Items in RadMenu for WinForms
6+
slug: menu-highlight-last-click-item
7+
tags: menus, winforms, menu-item, highlight
8+
res_type: kb
9+
ticketid: 1687046
10+
---
11+
12+
## Environment
13+
14+
|Product Version|Product|Author|
15+
|----|----|----|
16+
|2025.1.211|RadMenu for WinForms|[Dinko Krastev](https://www.telerik.com/blogs/author/dinko-krastev)|
17+
18+
## Description
19+
20+
A common requirement is to highlight the last selected RadMenuItem. This article will demonstrate how this can be achieved.
21+
22+
## Solution
23+
24+
RadMenu for WinForms does not support this behavior out of the box. To achieve it, use custom code to manage the highlighting of the menu items. Subscribe to the `Click` event of each `RadMenuItem` and implement logic to change the `BackColor` property of the clicked item while resetting the previous item's background.
25+
26+
### Example Code
27+
28+
Below is a code example demonstrating the custom solution:
29+
30+
````C#
31+
32+
public partial class Form2 : Form
33+
{
34+
public Form2()
35+
{
36+
InitializeComponent();
37+
DesertTheme desertTheme = new DesertTheme();
38+
ThemeResolutionService.ApplicationThemeName = desertTheme.ThemeName;
39+
foreach (RadMenuItem item in this.radMenu1.Items)
40+
{
41+
item.Click += RadMenuItem_Click;
42+
foreach (RadMenuItem subItem in item.Items)
43+
{
44+
subItem.Click += RadMenuItem_Click;
45+
}
46+
}
47+
}
48+
RadMenuItem lastSelectedMenuItem = null;
49+
RadMenuItem lastSelectedSubMenuItem = null;
50+
51+
void ResetColor(RadMenuItem radMenuItem)
52+
{
53+
if (radMenuItem != null)
54+
{
55+
radMenuItem.FillPrimitive.BackColor = Color.Transparent;
56+
radMenuItem.FillPrimitive.GradientStyle = GradientStyles.Linear;
57+
}
58+
}
59+
60+
void ResetColor(RadMenuItem radMenuItem)
61+
{
62+
if (radMenuItem != null)
63+
{
64+
radMenuItem.FillPrimitive.ResetValue(Telerik.WinControls.Primitives.FillPrimitive.BackColorProperty, Telerik.WinControls.ValueResetFlags.Local);
65+
radMenuItem.FillPrimitive.ResetValue(Telerik.WinControls.Primitives.FillPrimitive.GradientStyleProperty, Telerik.WinControls.ValueResetFlags.Local);
66+
}
67+
}
68+
69+
private void RadMenuItem_Click(object sender, EventArgs e)
70+
{
71+
var newSelectedMenuItem = sender as RadMenuItem;
72+
73+
if (newSelectedMenuItem != null)
74+
{
75+
if (lastSelectedMenuItem == null)
76+
{
77+
lastSelectedMenuItem = newSelectedMenuItem;
78+
ChangeColor(lastSelectedMenuItem);
79+
}
80+
else
81+
{
82+
var text1 = this.lastSelectedMenuItem.Text;
83+
var text2 = newSelectedMenuItem.Text;
84+
85+
if (newSelectedMenuItem.HierarchyParent is RadMenuItem parentMenuItem)
86+
{
87+
if (lastSelectedSubMenuItem != newSelectedMenuItem)
88+
{
89+
ResetColor(lastSelectedSubMenuItem);
90+
}
91+
lastSelectedSubMenuItem = newSelectedMenuItem;
92+
ChangeColor(lastSelectedSubMenuItem);
93+
94+
if (lastSelectedMenuItem != null)
95+
{
96+
ResetColor(lastSelectedMenuItem);
97+
}
98+
99+
lastSelectedMenuItem = parentMenuItem;
100+
ChangeColor(parentMenuItem);
101+
102+
}
103+
else
104+
{
105+
if (lastSelectedMenuItem == newSelectedMenuItem)
106+
{
107+
return;
108+
}
109+
if (lastSelectedSubMenuItem != null)
110+
{
111+
ResetColor(lastSelectedSubMenuItem);
112+
}
113+
114+
ResetColor(lastSelectedMenuItem);
115+
116+
lastSelectedMenuItem = newSelectedMenuItem;
117+
ChangeColor(newSelectedMenuItem);
118+
}
119+
}
120+
}
121+
}
122+
}
123+
124+
````
125+
126+
### Notes
127+
128+
- The code supports one level of subitems. For deeper hierarchies, extend the logic to support multiple levels of hierarchy.
129+
130+
## See Also
131+
132+
- [RadMenu Documentation](https://docs.telerik.com/devtools/winforms/controls/menus/menu/overview)

0 commit comments

Comments
 (0)