From f6c5e0a04d549b0062d661d514cb823e585d9c00 Mon Sep 17 00:00:00 2001 From: Dinko Krastev Date: Fri, 9 May 2025 17:11:24 +0300 Subject: [PATCH 1/3] KB-ChartView closest data point --- ...-scatterseries-closest-point-mouseclick.md | 115 ++++++++++++++++++ .../images/chartView-closestdatapoint.png | Bin 0 -> 5156 bytes 2 files changed, 115 insertions(+) create mode 100644 knowledge-base/chartview-scatterseries-closest-point-mouseclick.md create mode 100644 knowledge-base/images/chartView-closestdatapoint.png diff --git a/knowledge-base/chartview-scatterseries-closest-point-mouseclick.md b/knowledge-base/chartview-scatterseries-closest-point-mouseclick.md new file mode 100644 index 000000000..ad7bddf81 --- /dev/null +++ b/knowledge-base/chartview-scatterseries-closest-point-mouseclick.md @@ -0,0 +1,115 @@ +--- +title: Finding the Nearest ScatterDataPoint to a Mouse Click in RadChartView +description: Learn how to determine the closest ScatterDataPoint in a RadChartView when the user clicks within the chart area. +type: how-to +page_title: How to Identify the Closest ScatterDataPoint to a Mouse Click in RadChartView +slug: chartview-scatterseries-closest-point-mouseclick +tags: radchartview, scatterdatapoint, winforms, mouseeventargs, chart-axes +res_type: kb +ticketid: 1686235 +--- + +## Environment + +|Product Version|Product|Author| +|----|----|----| +|2025.1.211|RadTreeView for WinForms|[Dinko Krastev](https://www.telerik.com/blogs/author/dinko-krastev)| + +## Description + +This article will demonstrate how to determine the nearest ScatterDataPoint to a mouse click location using the mouse click position. + +## Solution + +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. + + 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. + +The following code snippet demonstrates a full implementation. + +````C# +public partial class Form1 : Form +{ + ScatterSeries scatterSeries = new ScatterSeries(); + public Form1() + { + InitializeComponent(); + scatterSeries.Name = ""; + scatterSeries.DataPoints.Add(new ScatterDataPoint(19000, 15)); + scatterSeries.DataPoints.Add(new ScatterDataPoint(10000, 18)); + scatterSeries.DataPoints.Add(new ScatterDataPoint(15000, 13)); + scatterSeries.DataPoints.Add(new ScatterDataPoint(80000, 10)); + scatterSeries.DataPoints.Add(new ScatterDataPoint(60000, 25)); + scatterSeries.PointSize = new SizeF(5, 5); + this.radChartView1.Series.Add(scatterSeries); + + this.radChartView1.MouseDown += RadChartView1_MouseDown; + } + private void RadChartView1_MouseDown(object sender, MouseEventArgs e) + { + Point pt = this.radChartView1.ChartElement.Wrapper.PointFromControl(e.Location); + double verticalValue = Convert.ToDouble(GetVerticalAxisValueFromMouse(e)); + double horizontalValue = Convert.ToDouble(GetHorizontalAxisValueFromMouse(e)); + + Debug.WriteLine("X: " + horizontalValue + " Y: " + verticalValue); + + ScatterDataPoint closestPoint = null; + double minDistance = double.MaxValue; + + var seriesToRemove = this.radChartView1.Series.FirstOrDefault(s => s.Name =="Closest Point"); + if (seriesToRemove != null) + { + this.radChartView1.Series.Remove(seriesToRemove); + } + foreach (ScatterDataPoint dataPoint in scatterSeries.DataPoints) + { + // Calculate the Euclidean distance + double distance = Math.Sqrt(Math.Pow(dataPoint.XValue - horizontalValue, 2) + Math.Pow((double)dataPoint.YValue - verticalValue, 2)); + // Update the closest point if the current distance is smaller + if (distance < minDistance) + { + minDistance = distance; + closestPoint = dataPoint; + } + } + + if (closestPoint != null) + { + var newScatterSeries = new ScatterSeries(); + newScatterSeries.Name = "Closest Point"; + newScatterSeries.DataPoints.Add(new ScatterDataPoint(closestPoint.XValue, (double)closestPoint.YValue)); + newScatterSeries.PointSize = new SizeF(15, 15); + newScatterSeries.BorderColor = Color.Red; + this.radChartView1.Series.Add(newScatterSeries); + this.radChartView1.Invalidate(); + this.radChartView1.Update(); + } + } + + private object GetHorizontalAxisValueFromMouse(MouseEventArgs e) + { + LinearAxis axis = radChartView1.Axes[0] as LinearAxis; + IChartView view = (IChartView)axis.View; + double delta = axis.ActualRange.Maximum - axis.ActualRange.Minimum; + double totalWidth = axis.Model.LayoutSlot.Width; + double ratio = 1 - (e.Location.X - this.radChartView1.Area.View.Viewport.X - view.PlotOriginX - axis.Model.LayoutSlot.X) / (totalWidth * view.ZoomWidth); + double value = axis.ActualRange.Minimum + delta * ratio; + return axis.ActualRange.Maximum - value; + } + private object GetVerticalAxisValueFromMouse(MouseEventArgs e) + { + LinearAxis axis = radChartView1.Axes[1] as LinearAxis; + IChartView view = (IChartView)axis.View; + double delta = axis.ActualRange.Maximum - axis.ActualRange.Minimum; + double totalHeight = axis.Model.LayoutSlot.Height; + double ratio = 1 - (e.Location.Y - this.radChartView1.Area.View.Viewport.Y - view.PlotOriginY - axis.Model.LayoutSlot.Y) / (totalHeight * view.ZoomHeight); + double value = axis.ActualRange.Minimum + delta * ratio; + return value; + } +} + +```` + +## See Also + +- [RadChartView Overview Documentation](https://docs.telerik.com/devtools/winforms/controls/chartview/overview) \ No newline at end of file diff --git a/knowledge-base/images/chartView-closestdatapoint.png b/knowledge-base/images/chartView-closestdatapoint.png new file mode 100644 index 0000000000000000000000000000000000000000..86cae01224099b7bd578d91137ad316552be8148 GIT binary patch literal 5156 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 Date: Mon, 12 May 2025 15:00:40 +0300 Subject: [PATCH 2/3] Update chartview-scatterseries-closest-point-mouseclick.md --- .../chartview-scatterseries-closest-point-mouseclick.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/knowledge-base/chartview-scatterseries-closest-point-mouseclick.md b/knowledge-base/chartview-scatterseries-closest-point-mouseclick.md index ad7bddf81..2605d337c 100644 --- a/knowledge-base/chartview-scatterseries-closest-point-mouseclick.md +++ b/knowledge-base/chartview-scatterseries-closest-point-mouseclick.md @@ -13,7 +13,7 @@ ticketid: 1686235 |Product Version|Product|Author| |----|----|----| -|2025.1.211|RadTreeView for WinForms|[Dinko Krastev](https://www.telerik.com/blogs/author/dinko-krastev)| +|2025.1.211|RadChartView for WinForms|[Dinko Krastev](https://www.telerik.com/blogs/author/dinko-krastev)| ## Description @@ -112,4 +112,4 @@ public partial class Form1 : Form ## See Also -- [RadChartView Overview Documentation](https://docs.telerik.com/devtools/winforms/controls/chartview/overview) \ No newline at end of file +- [RadChartView Overview Documentation](https://docs.telerik.com/devtools/winforms/controls/chartview/overview) From 2944a8b8ddc7acdb5f822ea45d4b786c4c0db25e Mon Sep 17 00:00:00 2001 From: Dinko Krastev Date: Mon, 12 May 2025 15:33:04 +0300 Subject: [PATCH 3/3] Add missing image, Add another KB --- ...-scatterseries-closest-point-mouseclick.md | 2 + .../menu-highlight-last-click-item.md | 132 ++++++++++++++++++ 2 files changed, 134 insertions(+) create mode 100644 knowledge-base/menu-highlight-last-click-item.md diff --git a/knowledge-base/chartview-scatterseries-closest-point-mouseclick.md b/knowledge-base/chartview-scatterseries-closest-point-mouseclick.md index ad7bddf81..8fa7fb8f0 100644 --- a/knowledge-base/chartview-scatterseries-closest-point-mouseclick.md +++ b/knowledge-base/chartview-scatterseries-closest-point-mouseclick.md @@ -19,6 +19,8 @@ ticketid: 1686235 This article will demonstrate how to determine the nearest ScatterDataPoint to a mouse click location using the mouse click position. +![WinForms RadChartView ClosestDataPoint](images/chartView-closestdatapoint.png) + ## Solution 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. diff --git a/knowledge-base/menu-highlight-last-click-item.md b/knowledge-base/menu-highlight-last-click-item.md new file mode 100644 index 000000000..f604bd699 --- /dev/null +++ b/knowledge-base/menu-highlight-last-click-item.md @@ -0,0 +1,132 @@ +--- +title: Highlight the Last Selected Menu Item In RadMenu +description: Learn how to keep selected menu items highlighted in RadMenu for WinForms by implementing custom code. +type: how-to +page_title: Highlighting Selected Menu Items in RadMenu for WinForms +slug: menu-highlight-last-click-item +tags: menus, winforms, menu-item, highlight +res_type: kb +ticketid: 1687046 +--- + +## Environment + +|Product Version|Product|Author| +|----|----|----| +|2025.1.211|RadMenu for WinForms|[Dinko Krastev](https://www.telerik.com/blogs/author/dinko-krastev)| + +## Description + +A common requirement is to highlight the last selected RadMenuItem. This article will demonstrate how this can be achieved. + +## Solution + +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. + +### Example Code + +Below is a code example demonstrating the custom solution: + +````C# + +public partial class Form2 : Form +{ + public Form2() + { + InitializeComponent(); + DesertTheme desertTheme = new DesertTheme(); + ThemeResolutionService.ApplicationThemeName = desertTheme.ThemeName; + foreach (RadMenuItem item in this.radMenu1.Items) + { + item.Click += RadMenuItem_Click; + foreach (RadMenuItem subItem in item.Items) + { + subItem.Click += RadMenuItem_Click; + } + } + } + RadMenuItem lastSelectedMenuItem = null; + RadMenuItem lastSelectedSubMenuItem = null; + + void ResetColor(RadMenuItem radMenuItem) + { + if (radMenuItem != null) + { + radMenuItem.FillPrimitive.BackColor = Color.Transparent; + radMenuItem.FillPrimitive.GradientStyle = GradientStyles.Linear; + } + } + + void ResetColor(RadMenuItem radMenuItem) +{ + if (radMenuItem != null) + { + radMenuItem.FillPrimitive.ResetValue(Telerik.WinControls.Primitives.FillPrimitive.BackColorProperty, Telerik.WinControls.ValueResetFlags.Local); + radMenuItem.FillPrimitive.ResetValue(Telerik.WinControls.Primitives.FillPrimitive.GradientStyleProperty, Telerik.WinControls.ValueResetFlags.Local); + } +} + + private void RadMenuItem_Click(object sender, EventArgs e) + { + var newSelectedMenuItem = sender as RadMenuItem; + + if (newSelectedMenuItem != null) + { + if (lastSelectedMenuItem == null) + { + lastSelectedMenuItem = newSelectedMenuItem; + ChangeColor(lastSelectedMenuItem); + } + else + { + var text1 = this.lastSelectedMenuItem.Text; + var text2 = newSelectedMenuItem.Text; + + if (newSelectedMenuItem.HierarchyParent is RadMenuItem parentMenuItem) + { + if (lastSelectedSubMenuItem != newSelectedMenuItem) + { + ResetColor(lastSelectedSubMenuItem); + } + lastSelectedSubMenuItem = newSelectedMenuItem; + ChangeColor(lastSelectedSubMenuItem); + + if (lastSelectedMenuItem != null) + { + ResetColor(lastSelectedMenuItem); + } + + lastSelectedMenuItem = parentMenuItem; + ChangeColor(parentMenuItem); + + } + else + { + if (lastSelectedMenuItem == newSelectedMenuItem) + { + return; + } + if (lastSelectedSubMenuItem != null) + { + ResetColor(lastSelectedSubMenuItem); + } + + ResetColor(lastSelectedMenuItem); + + lastSelectedMenuItem = newSelectedMenuItem; + ChangeColor(newSelectedMenuItem); + } + } + } + } +} + +```` + +### Notes + +- The code supports one level of subitems. For deeper hierarchies, extend the logic to support multiple levels of hierarchy. + +## See Also + +- [RadMenu Documentation](https://docs.telerik.com/devtools/winforms/controls/menus/menu/overview) \ No newline at end of file