This article provides a detailed walkthrough on how to add multiple trackballs in an WPF Chart , allowing you to hover over the trackball with your mouse and move them independently to view the information of different data points simultaneously. Learn step-by-step instructions and gain insights to add multiple trackballs in a WPF SfChart. Step 1: Initialize the SfChart with primary and secondary axes. For more detailed steps, refer to the WPF Charts documentation. XAML <Grid> <chart:SfChart x:Name="chart"> <chart:SfChart.PrimaryAxis> <chart:CategoryAxis/> </chart:SfChart.PrimaryAxis> <chart:SfChart.SecondaryAxis> <chart:NumericalAxis/> </chart:SfChart.SecondaryAxis> <chart:LineSeries ItemsSource="{Binding Data}" XBindingPath="Day" YBindingPath="CPULoad" > </chart:LineSeries> </chart:SfChart> </Grid> Step 2: Create a custom ChartTrackBallBehaviorExt class, which is inherited from ChartTrackballBehavior. C# public class ChartTrackBallBehaviorExt : ChartTrackBallBehavior { } Step 3: Create instances of ChartTrackBallBehaviorExt, and add them to the Behaviors collection, assigning specific names to each. XAML <chart:SfChart.Behaviors> <local:ChartTrackBallBehaviorExt x:Name="trackball1"/> <local:ChartTrackBallBehaviorExt x:Name="trackball2"/> </chart:SfChart.Behaviors> Step 4: Implement the ChartTrackBallBehaviorExt class and its functionalities. Include the Display method, which is responsible for displaying the trackball at specified coordinates by setting the IsActivated protected property of the ChartTrackBallBehavior class. Manage multiple trackballs by overriding mouse event handlers in ChartTrackBallBehavior, using the FindNearestTrackball method in OnMouseEnter to locate the closest trackball. The isTrackballActive variable ensures only the active trackball responds to the events. public class ChartTrackBallBehaviorExt : ChartTrackBallBehavior { private bool isTrackballActive = false; public SfChart? SfChart { get; set; } public double X { get; set; } public double Y { get; set; } protected override void OnMouseEnter(MouseEventArgs e) { // Get the position of the mouse pointer var touchPoint = e.GetPosition(null); // Find the nearest trackball to the mouse pointer var trackball = FindNearestTrackball(touchPoint); // Activate the trackball if it is the nearest one if (trackball == this) { isTrackballActive = true; base.OnMouseEnter(e); } } protected override void OnMouseMove(MouseEventArgs e) { // Check if the trackball is activated if (isTrackballActive) { // Get the position of the mouse pointer var touchPoint = e.GetPosition(null); // Display the trackball at the current mouse position Display((float)touchPoint.X, (float)touchPoint.Y); base.OnMouseMove(e); } } protected override void OnMouseLeave(MouseEventArgs e) { // Deactivate the trackball isTrackballActive = false; } private ChartTrackBallBehavior FindNearestTrackball(Point touchPoint) { ChartTrackBallBehavior nearestTrackball = new ChartTrackBallBehaviorExt(); double minDistance = double.MaxValue; // Iterate through all trackball behaviors to find the nearest one if (SfChart != null) { foreach (var trackballBehaviour in SfChart.Behaviors) { if (trackballBehaviour is ChartTrackBallBehaviorExt trackball) { // Calculate the distance between the trackball and the touch point double distance = Math.Sqrt(Math.Pow(trackball.X - touchPoint.X, 2) + Math.Pow(trackball.Y - touchPoint.Y, 2)); // Update the nearest trackball if the current one is closer if (distance < minDistance) { minDistance = distance; nearestTrackball = trackball; } } } } return nearestTrackball; } public void Display(float x, float y) { X = x; Y = y; IsActivated = true; var point = new Point(x, y); // Set the internal property for the current point SetInternalProperty(typeof(ChartTrackBallBehavior), this, point, "CurrentPoint"); // Trigger the pointer position changed event base.OnPointerPositionChanged(); // Activate the trackball InvokeInternalMethod(typeof(ChartTrackBallBehavior), this, "Activate", IsActivated); } // Sets an internal property of an object using reflection. internal static void SetInternalProperty(Type type, object obj, object value, string propertyName) { var properties = type.GetRuntimeProperties(); foreach (var item in properties) { if (item.Name == propertyName) { item.SetValue(obj, value); break; } } } // Invokes an internal method of an object using reflection. internal static object? InvokeInternalMethod(Type type, object obj, string methodName, params object[] args) { var method = type.GetTypeInfo().GetDeclaredMethod(methodName); return method?.Invoke(obj, args); } } Step 5: Assign the chart instance to the SfChart property in the ChartTrackBallBehaviorExt class, and override the OnContentRendered method to run an asynchronous task that calls ShowTrackball method. The ShowTrackball method calculates the positions and displays the trackballs on the chart. C# public partial class MainWindow : Window { public MainWindow() { InitializeComponent(); trackball1.SfChart = this.chart; trackball2.SfChart = this.chart; } protected override void OnContentRendered(EventArgs e) { base.OnContentRendered(e); // Run the ShowTrackball method asynchronously Task.Run(async () => { await ShowTrackball(); }); } async Task ShowTrackball() { // Wait for 1 second before executing the rest of the method await Task.Delay(1000); Application.Current.Dispatcher.Invoke(() => { // Calculated positions for the first trackball float xPosition = (float)chart.ValueToPoint(chart.PrimaryAxis, 1); float yPosition = (float)chart.ValueToPoint(chart.SecondaryAxis, 169); // Calculated positions for the second trackball float xPosition1 = (float)chart.ValueToPoint(chart.PrimaryAxis, 6); float yPosition1 = (float)chart.ValueToPoint(chart.SecondaryAxis, 170); // Display the first trackball trackball1.Display(xPosition, yPosition); // Display the second trackball trackball2.Display(xPosition1, yPosition1); }); } } Step 6: To control the trackballs, simply hover over them with your mouse. As you move the mouse within the chart area, the trackball will follow the cursor, allowing you to inspect different data points interactively. Output: Explore the runnable demo from this GitHub location. Conclusion: I hope you enjoyed learning about how to add and customize multiple trackballs in WPF Chart. You can refer to our WPF Chart feature tour page to know about its other groundbreaking feature representations and documentation, and how to quickly get started for configuration specifications. For current customers, you can check out our components from the License and Downloads page. If you are new to Syncfusion®, you can try our 30-day free trial to check out our other controls. If you have any queries or require clarifications, please let us know in the comments section below. You can also contact us through our support forums, Direct-Trac, or feedback portal. We are always happy to assist you!
SfChart allows you add multiple trackballs to a single chart and drag them independently to view the information of different data points at the same time. The following steps describe how to add multiple trackballs to SfChart. Step 1: Create a custom ChartTrackballBehaviorExt class, which is inherited from ChartTrackballBehavior. public class ChartTrackballBehaviorExt : ChartTrackballBehavior { } Step 2: Create an instance of ChartTrackballBehaviorExt and add it to the Behaviors collection. ChartTrackballBehaviorExt trackballBehavior1 = new ChartTrackballBehaviorExt(); ChartTrackballBehaviorExt trackballBehavior2 = new ChartTrackballBehaviorExt(); chart.Behaviors.Add(trackballBehavior1); chart.Behaviors.Add(trackballBehavior2); Step 3: Activate the multiple trackballs at load time using the Show method. public override void OnAttachedToWindow() { base.OnAttachedToWindow(); Task.Run(async () => { await ShowTrackball(); }); } async Task ShowTrackball() { Task.Delay(1000).Wait(); trackballBehavior1.Show(pointX, pointY); trackballBehavior2.Show(pointX, pointY); } Step 4: Set ActivationMode to None to restrict the default movement of the trackball behavior. trackballBehavior1.ActivationMode = ChartTrackballActivationMode.None; trackballBehavior2.ActivationMode = ChartTrackballActivationMode.None; Step 5: Interact with multiple trackballs by overriding the touch methods of ChartTrackballBehavior class and the HitTest method. The HitTest method is used to find the trackball that is currently activated by user. public class ChartTrackballBehaviorExt : ChartTrackballBehavior { bool isActivated= false; protected override void OnTouchDown(float pointX, float pointY) { if (HitTest(pointX, pointY)) { isActivated= true; base.OnTouchDown(pointX, pointY); } } protected override void OnTouchMove(float pointX, float pointY) { if (isActivated) { Show(pointX, pointY); base.OnTouchMove(pointX, pointY); } } protected override void OnTouchUp(float pointX, float pointY) { isActivated= false; } } Step 6: Tap and drag each trackball separately to view the data points at different positions simultaneously. Output ConclusionI hope you enjoyed learning about how to add the multiple trackball in Xamarin.Android charts.You can refer to our Xamarin.Android Charts feature tour page to know about its other groundbreaking feature representations and documentation, and how to quickly get started for configuration specifications.For current customers, you can check out our components from the License and Downloads page. If you are new to Syncfusion, you can try our 30-day free trialto check out our other controls.If you have any queries or require clarifications, please let us know in the comments section below. You can also contact us through our support forums, Direct-Trac, or feedback portal. We are always happy to assist you!
SFChart allows you add multiple trackballs to a single chart and drag them independently to view the information of different data points at the same time. The following steps describe how to add multiple trackballs to SFChart. Step 1: Create a custom ChartTrackballBehaviorExt class, which is inherited from SFChartTrackballBehavior. public class ChartTrackballBehaviorExt : SFChartTrackballBehavior { } Step 2: Create an instance of ChartTrackballBehaviorExt and add it to the Behaviors collection. ChartTrackballBehaviorExt trackballBehavior1 = new ChartTrackballBehaviorExt(); ChartTrackballBehaviorExt trackballBehavior2 = new ChartTrackballBehaviorExt(); chart.Behaviors.Add(trackballBehavior1); chart.Behaviors.Add(trackballBehavior2); Step 3: Activate the multiple trackballs at load time using the Show method. public override void ViewDidAppear(bool animated) { base.ViewDidAppear(animated); trackballBehavior1.Show(pointX, pointY); trackballBehavior2.Show(pointX, pointY); } Step 4: Set ActivationMode to None to restrict the default movement of the trackball behavior. trackballBehavior1.ActivationMode = SFChartTrackballActivationMode.None; trackballBehavior2.ActivationMode = SFChartTrackballActivationMode.None; Step 5: Interact with multiple trackballs by overriding the touch methods of SFChartTrackballBehavior class and the HitTest method. The HitTest method is used to find the trackball that is currently activated by user. public class ChartTrackballBehaviorExt : SFChartTrackballBehavior { bool isActivated = false; public override void TouchesBegan(NSSet touches, UIEvent uiEvent) { if (touches?.AnyObject is UITouch touch) { CGPoint location = touch.LocationInView(Chart); if (HitTest((float)location.X, (float)location.Y)) { isActivated = true; base.TouchesBegan(touches, uiEvent); } } } public override void TouchesMoved(NSSet touches, UIEvent uiEvent) { if (isActivated) { if (touches?.AnyObject is UITouch touch) { CGPoint location = touch.LocationInView(Chart); Show(location); base.TouchesMoved(touches, uiEvent); } } } public override void TouchesEnded(NSSet touches, UIEvent uiEvent) { isActivated = false; } } Step 6: Tap and drag each trackball separately to view the data points at different positions simultaneously. Output:
Xamarin Chart allows you add multiple trackballs to a single chart and drag them independently to view the information of different data points at the same time. The following steps describe how to add multiple trackballs to SfChart and you can download the complete sample here: Step 1: Create a custom ChartTrackballBehaviorExt class, which is inherited from ChartTrackballBehavior. C#: public class ChartTrackballBehaviorExt : ChartTrackballBehavior { } Step 2: Create an instance of ChartTrackballBehaviorExt, and add it to the ChartBehaviors collection. XAML: <chart:SfChart.ChartBehaviors> <local:ChartTrackballBehaviorExt /> <local:ChartTrackballBehaviorExt /> </chart:SfChart.ChartBehaviors> Step 3: Activate the multiple trackballs at load time using the Show method. C#: protected override void OnAppearing() { base.OnAppearing(); Task.Run(async () => { await ShowTrackball(); }); } async Task ShowTrackball() { Task.Delay(1000).Wait(); Device.BeginInvokeOnMainThread(() => { trackballBehavior1.Show(pointX, pointY); trackballBehavior2.Show(pointX, pointY); }); } Step 4: Set ActivationMode to None to restrict the default movement of the trackball behavior. XAML: <chart:SfChart.ChartBehaviors> <local:ChartTrackballBehaviorExt ActivationMode="None" x:Name="trackballBehavior1" /> <local:ChartTrackballBehaviorExt ActivationMode="None" x:Name="trackballBehavior2" /> </chart:SfChart.ChartBehaviors> Step 5: Interact with multiple trackballs by overriding the touch methods of ChartTrackballBehavior class and the HitTest method. The HitTest method is used to find the trackball that is currently activated by user. C#: public class ChartTrackballBehaviorExt : ChartTrackballBehavior { bool isActivated = false; protected override void OnTouchDown(float pointX, float pointY) { if (HitTest(pointX, pointY)) { isActivated = true; base.OnTouchDown(pointX, pointY); } } protected override void OnTouchMove(float pointX, float pointY) { if (isActivated) { Show(pointX, pointY); base.OnTouchMove(pointX, pointY); } } protected override void OnTouchUp(float pointX, float pointY) { isActivated = false; } } Step 6: Tap and drag each trackball separately to view the data points at different positions simultaneously. Output: ConclusionI hope you enjoyed learning how to w to add multiple trackballs in Xamarin.Forms Chart.You can refer to our Xamarin. Forms Chart feature tour page to know about its other groundbreaking feature representations and documentation, and how to quickly get started for configuration specifications. You can also explore our Xamarin. Forms Charts example to understand how to create and manipulate data.For current customers, you can check out our components from the License and Downloads page. If you are new to Syncfusion, you can try our 30-day free trial to check out our other controls.If you have any queries or require clarifications, please let us know in the comments section below. You can also contact us through our support forums, Direct-Trac, or feedback portal. We are always happy to assist you!