diff --git a/README.md b/README.md index 6cd6e43..71a5006 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,137 @@ -# How-to-Synchronize-Panning-in-Multiple-WPF-Charts. -This article explains how to synchronize panning in multiple WPF charts with step-by-step guidance. +# How-to-Synchronize-Panning-in-Multiple-WPF-Charts + +Synchronizing panning across multiple charts in a WPF application can enhance the user experience by allowing users to view related data simultaneously. This article outlines the steps to achieve synchronized panning in [Syncfusion WPF SfCharts](https://www.syncfusion.com/wpf-controls/charts). + +## Steps to achieve Synchronized Panning in Multiple Charts + +1. Set Up Multiple Charts + +Let’s configure the Syncfusion WPF Chart control using this [getting started documentation](https://help.syncfusion.com/wpf/charts/getting-started). Refer to the following code example to create multiple charts in your application. + + + ``` + +. . . . + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +. . . . + + ``` + + +2. Enable Zoom Pan behavior for each Chart + +The panning feature enables moving the visible area of the chart when zoomed in. To activate panning, set the [**EnablePanning**](https://help.syncfusion.com/cr/wpf/Syncfusion.UI.Xaml.Charts.ChartZoomPanBehavior.html#Syncfusion_UI_Xaml_Charts_ChartZoomPanBehavior_EnablePanning) property to true. + + + ``` + +. . . + + + + + +. . . + + ``` + + +3. Handle the Zooming and Panning changed events + +This event tracks the changes in the visible area and update the viewports of other charts to match the new range. + +[XAML] + + ``` + +. . . + + + + + +. . . + + ``` + +[C#] + + ``` +private void Chart_ZoomChanging(object sender, ZoomChangingEventArgs e) +{ + SfChart sourceChart = (SfChart)sender; + foreach (var chart in new[] { StepLineChart, SplineChart, AreaChart }) + { + if (chart != sourceChart) + { + chart.PrimaryAxis.ZoomFactor = e.CurrentFactor; + chart.PrimaryAxis.ZoomPosition = e.CurrentPosition; + } + } +} + +private void Chart_PanChanging(object sender, PanChangingEventArgs e) +{ + SfChart sourceChart = (SfChart)sender; + foreach (var chart in new[] { StepLineChart, SplineChart, AreaChart }) + { + if (chart != sourceChart) + { + chart.PrimaryAxis.ZoomPosition = e.NewZoomPosition; + chart.PrimaryAxis.ZoomFactor = e.Axis.ZoomFactor; + } + } +} + ``` + +## Output + +The following demo video illustrates multiple Charts in WPF with synchronized panning, showing how the visible areas of the charts move together when panning is performed on any one chart, following the implemented synchronization steps. + + ![Synchronize_Panning_in_WPF_Multiple_Charts_Converted.gif](https://support.syncfusion.com/kb/agent/attachment/article/18329/inline?token=eyJhbGciOiJodHRwOi8vd3d3LnczLm9yZy8yMDAxLzA0L3htbGRzaWctbW9yZSNobWFjLXNoYTI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6IjM0MDU2Iiwib3JnaWQiOiIzIiwiaXNzIjoic3VwcG9ydC5zeW5jZnVzaW9uLmNvbSJ9.FobbwZhJqvlfBurJe9ctvqCVvSEnFHXKQrZVGVybq2I) + +## Troubleshooting + +#### Path too long exception + +If you are facing a path too long exception when building this example project, close Visual Studio and rename the repository to a shorter name before building the project. + +For more details, refer to the KB on [how to synchronize panning in WPF chart control?](https://support.syncfusion.com/kb/article/18329/how-to-synchronize-panning-in-wpf-charts). \ No newline at end of file diff --git a/SynchronizePanningSampleWPF/App.xaml b/SynchronizePanningSampleWPF/App.xaml new file mode 100644 index 0000000..6b1cf23 --- /dev/null +++ b/SynchronizePanningSampleWPF/App.xaml @@ -0,0 +1,9 @@ + + + + + diff --git a/SynchronizePanningSampleWPF/App.xaml.cs b/SynchronizePanningSampleWPF/App.xaml.cs new file mode 100644 index 0000000..0a1ad95 --- /dev/null +++ b/SynchronizePanningSampleWPF/App.xaml.cs @@ -0,0 +1,14 @@ +using System.Configuration; +using System.Data; +using System.Windows; + +namespace SynchronizePanningSampleWPF +{ + /// + /// Interaction logic for App.xaml + /// + public partial class App : Application + { + } + +} diff --git a/SynchronizePanningSampleWPF/AssemblyInfo.cs b/SynchronizePanningSampleWPF/AssemblyInfo.cs new file mode 100644 index 0000000..b0ec827 --- /dev/null +++ b/SynchronizePanningSampleWPF/AssemblyInfo.cs @@ -0,0 +1,10 @@ +using System.Windows; + +[assembly: ThemeInfo( + ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located + //(used if a resource is not found in the page, + // or application resource dictionaries) + ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located + //(used if a resource is not found in the page, + // app, or any theme specific resource dictionaries) +)] diff --git a/SynchronizePanningSampleWPF/MainWindow.xaml b/SynchronizePanningSampleWPF/MainWindow.xaml new file mode 100644 index 0000000..140ab76 --- /dev/null +++ b/SynchronizePanningSampleWPF/MainWindow.xaml @@ -0,0 +1,73 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/SynchronizePanningSampleWPF/MainWindow.xaml.cs b/SynchronizePanningSampleWPF/MainWindow.xaml.cs new file mode 100644 index 0000000..5b066d4 --- /dev/null +++ b/SynchronizePanningSampleWPF/MainWindow.xaml.cs @@ -0,0 +1,39 @@ +namespace SynchronizePanningSampleWPF +{ + using Syncfusion.UI.Xaml.Charts; + using System.Windows; + + public partial class MainWindow : Window + { + public MainWindow() + { + InitializeComponent(); + } + + private void Chart_ZoomChanging(object sender, ZoomChangingEventArgs e) + { + SfChart sourceChart = (SfChart)sender; + foreach (var chart in new[] { StepLineChart, SplineChart, AreaChart }) + { + if (chart != sourceChart) + { + chart.PrimaryAxis.ZoomFactor = e.CurrentFactor; + chart.PrimaryAxis.ZoomPosition = e.CurrentPosition; + } + } + } + + private void Chart_PanChanging(object sender, PanChangingEventArgs e) + { + SfChart sourceChart = (SfChart)sender; + foreach (var chart in new[] { StepLineChart, SplineChart, AreaChart }) + { + if (chart != sourceChart) + { + chart.PrimaryAxis.ZoomPosition = e.NewZoomPosition; + chart.PrimaryAxis.ZoomFactor = e.Axis.ZoomFactor; + } + } + } + } +} \ No newline at end of file diff --git a/SynchronizePanningSampleWPF/Model/ChartData.cs b/SynchronizePanningSampleWPF/Model/ChartData.cs new file mode 100644 index 0000000..ea1752a --- /dev/null +++ b/SynchronizePanningSampleWPF/Model/ChartData.cs @@ -0,0 +1,8 @@ +namespace SynchronizePanningSampleWPF +{ + public class ChartData + { + public double X { get; set; } + public double Y { get; set; } + } +} diff --git a/SynchronizePanningSampleWPF/SynchronizePanningSampleWPF.csproj b/SynchronizePanningSampleWPF/SynchronizePanningSampleWPF.csproj new file mode 100644 index 0000000..195e784 --- /dev/null +++ b/SynchronizePanningSampleWPF/SynchronizePanningSampleWPF.csproj @@ -0,0 +1,15 @@ + + + + WinExe + net9.0-windows + enable + enable + true + + + + + + + diff --git a/SynchronizePanningSampleWPF/SynchronizePanningSampleWPF.csproj.user b/SynchronizePanningSampleWPF/SynchronizePanningSampleWPF.csproj.user new file mode 100644 index 0000000..644b0a6 --- /dev/null +++ b/SynchronizePanningSampleWPF/SynchronizePanningSampleWPF.csproj.user @@ -0,0 +1,14 @@ + + + + + + Designer + + + + + Designer + + + \ No newline at end of file diff --git a/SynchronizePanningSampleWPF/SynchronizePanningSampleWPF.sln b/SynchronizePanningSampleWPF/SynchronizePanningSampleWPF.sln new file mode 100644 index 0000000..03406ec --- /dev/null +++ b/SynchronizePanningSampleWPF/SynchronizePanningSampleWPF.sln @@ -0,0 +1,22 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.12.35527.113 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SynchronizePanningSampleWPF", "SynchronizePanningSampleWPF.csproj", "{D887EC71-A5D6-4E0D-8101-88381C2F01B8}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {D887EC71-A5D6-4E0D-8101-88381C2F01B8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {D887EC71-A5D6-4E0D-8101-88381C2F01B8}.Debug|Any CPU.Build.0 = Debug|Any CPU + {D887EC71-A5D6-4E0D-8101-88381C2F01B8}.Release|Any CPU.ActiveCfg = Release|Any CPU + {D887EC71-A5D6-4E0D-8101-88381C2F01B8}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/SynchronizePanningSampleWPF/ViewModel/ChartViewModel.cs b/SynchronizePanningSampleWPF/ViewModel/ChartViewModel.cs new file mode 100644 index 0000000..74c0b45 --- /dev/null +++ b/SynchronizePanningSampleWPF/ViewModel/ChartViewModel.cs @@ -0,0 +1,74 @@ +namespace SynchronizePanningSampleWPF +{ + using System.Collections.ObjectModel; + + public class ChartViewModel + { + public ObservableCollection StepLineChartData { get; set; } + public ObservableCollection SplineChartData { get; set; } + public ObservableCollection AreaChartData { get; set; } + + public ChartViewModel() + { + // Data for StepLine Chart + StepLineChartData = new ObservableCollection() + { + new ChartData { X = 0, Y = 4 }, + new ChartData { X = 1, Y = 6 }, + new ChartData { X = 2, Y = 5 }, + new ChartData { X = 3, Y = 8 }, + new ChartData { X = 4, Y = 10 }, + new ChartData { X = 5, Y = 7 }, + new ChartData { X = 6, Y = 12 }, + new ChartData { X = 7, Y = 9 }, + new ChartData { X = 8, Y = 11 }, + new ChartData { X = 9, Y = 6 }, + new ChartData { X = 10, Y = 8 }, + new ChartData { X = 11, Y = 10 }, + new ChartData { X = 12, Y = 13 }, + new ChartData { X = 13, Y = 9 }, + new ChartData { X = 14, Y = 14 } + }; + + // Data for Spline Chart + SplineChartData = new ObservableCollection() + { + new ChartData { X = 0, Y = 3 }, + new ChartData { X = 1, Y = 5 }, + new ChartData { X = 2, Y = 4 }, + new ChartData { X = 3, Y = 6 }, + new ChartData { X = 4, Y = 8 }, + new ChartData { X = 5, Y = 7 }, + new ChartData { X = 6, Y = 9 }, + new ChartData { X = 7, Y = 6 }, + new ChartData { X = 8, Y = 10 }, + new ChartData { X = 9, Y = 12 }, + new ChartData { X = 10, Y = 8 }, + new ChartData { X = 11, Y = 11 }, + new ChartData { X = 12, Y = 13 }, + new ChartData { X = 13, Y = 10 }, + new ChartData { X = 14, Y = 14 } + }; + + // Data for Area Chart + AreaChartData = new ObservableCollection() + { + new ChartData { X = 0, Y = 5 }, + new ChartData { X = 1, Y = 7 }, + new ChartData { X = 2, Y = 6 }, + new ChartData { X = 3, Y = 9 }, + new ChartData { X = 4, Y = 11 }, + new ChartData { X = 5, Y = 8 }, + new ChartData { X = 6, Y = 10 }, + new ChartData { X = 7, Y = 7 }, + new ChartData { X = 8, Y = 12 }, + new ChartData { X = 9, Y = 9 }, + new ChartData { X = 10, Y = 11 }, + new ChartData { X = 11, Y = 13 }, + new ChartData { X = 12, Y = 15 }, + new ChartData { X = 13, Y = 12 }, + new ChartData { X = 14, Y = 14 } + }; + } + } +}