I recently posted a video demonstrating how to implement some extension methods to support xamDataChart navigation. The navigation support implemented in the demo included:
- PanUp
- PanDown
- PanLeft
- PanRight
- ZoomIn
- ZoomOut
- FitInWindow
The only problem with the code I used in the video, was that the event handler for the buttons included a long if statement to handle navigation support. As the famous quote goes, “If it smells, it’s bad code”, so I wanted to refactor the implementation to be a bit more maintainable. Before I get into the changes, I first want to list the extension methods that I implemented in order to make it easy to pan and zoom the chart. Notice that the methods us a default scale value so you are not required to pass in a scale amount for each method call.
public static class xamDataChartExtensions
{
private static double _defaultScale = 0.05;
public static void ZoomIn(this XamDataChart dataChart)
{
ZoomIn(dataChart, _defaultScale);
}
public static void ZoomIn(this XamDataChart dataChart, double scale)
{
dataChart.WindowScaleHorizontal -= scale;
dataChart.WindowScaleVertical -= scale;
}
public static void ZoomOut(this XamDataChart dataChart)
{
ZoomOut(dataChart, _defaultScale);
}
public static void ZoomOut(this XamDataChart dataChart, double scale)
{
dataChart.WindowScaleHorizontal += scale;
dataChart.WindowScaleVertical += scale;
}
public static void PanUp(this XamDataChart dataChart)
{
PanUp(dataChart, _defaultScale);
}
public static void PanUp(this XamDataChart dataChart, double scale)
{
dataChart.WindowPositionVertical -= scale;
}
public static void PanDown(this XamDataChart dataChart)
{
PanDown(dataChart, _defaultScale);
}
public static void PanDown(this XamDataChart dataChart, double scale)
{
dataChart.WindowPositionVertical += scale;
}
public static void PanLeft(this XamDataChart dataChart)
{
PanLeft(dataChart, _defaultScale);
}
public static void PanLeft(this XamDataChart dataChart, double scale)
{
dataChart.WindowPositionHorizontal -= scale;
}
public static void PanRight(this XamDataChart dataChart)
{
PanRight(dataChart, _defaultScale);
}
public static void PanRight(this XamDataChart dataChart, double scale)
{
dataChart.WindowPositionHorizontal += scale;
}
The previous code I implemented featured a nested if statement that would call the appropriate extension method, but I knew there was an easy way to clean this code out of the page. The key to a more concise approach begins by defining a enumeration which lists the navigation options:
public enum xamDataChartNavigationTypes
{
PanUp,
PanDown,
PanLeft,
PanRight,
ZoomIn,
ZoomOut,
FitInWindow,
Undefined
}
Now armed with the navigation enumeration I added another extension method named Navigate which takes an instance of the navigation enumeration and an option to pass an explicit scale value:
public static void Navigate(this XamDataChart dataChart, xamDataChartNavigationTypes navigationType)
{
Navigate(dataChart, navigationType, _defaultScale);
}
public static void Navigate(this XamDataChart dataChart, xamDataChartNavigationTypes navigationType, double scale)
{
switch (navigationType)
{
case xamDataChartNavigationTypes.FitInWindow:
dataChart.WindowRect = new Rect(0, 0, 1, 1);
break;
case xamDataChartNavigationTypes.PanUp:
dataChart.PanUp(scale);
break;
case xamDataChartNavigationTypes.PanDown:
dataChart.PanDown(scale);
break;
case xamDataChartNavigationTypes.PanLeft:
dataChart.PanLeft(scale);
break;
case xamDataChartNavigationTypes.PanRight:
dataChart.PanRight(scale);
break;
case xamDataChartNavigationTypes.ZoomIn:
dataChart.ZoomIn(scale);
break;
case xamDataChartNavigationTypes.ZoomOut:
dataChart.ZoomOut(scale);
break;
default:
break;
}
}
Now as long at the Tag property of your button is equal to one of the navigation enumeration values (ex: PanUp, PanDown, etc), then the click handler is reduced to the following:
private void Navigate_Click(object sender, RoutedEventArgs e)
{
string tag = (sender as Button).Tag.ToString();
xamDataChartNavigationTypes navigationType;
if (xamDataChartNavigationTypes.TryParse(tag, out navigationType))
{
this.dataChart.Navigate(navigationType);
}
}