11 Answers, 1 is accepted
In a first answer I can tell you that you can zoom out. Notice that slide bar on chart shrinks when you zoom in... if you grab one extremity and drag direction out you will be doing zoom out.
err.. this is about "ChartView"! on chart you will have to set Command available to that feature. I know I have already seen a project demo for that feature.
As for another methods for zoom out I am also looking that since this is not so intuitiveness. I am looking for something perhaps like zoom in and out on mouse wheel.
If I find out how I will tell you.
I will try to answer both your questions together. Although each of you are asking about features of two different controls, the principle is the same and the controls are very similar.
First let me get to Anita's question:
Yes, you can scroll and zoom using RadChart. This documentation will show you how to implement that feature in your RadChart. Before you start doing that though, I recommend you check out this example telerik uses to show the feature in action. Read the description on the left side of the demo to learn more. Play with the demo for a minute and visualize how you want it to work in your application.
If you need any additional help implementing it, let me know and we can go through your code directly.
Now on to Ricardo's Question:
If I understand you correctly, you are asking specifically about RadChartView, which is a different control than RadChart. RadChartView provides zoom and scroll interactivity with the ChartPanAndZoomBehavior class. If you want to add additional functionality to the control, for instance with a mouse scrollwheel, you can subscribe to the mouse's events. When the mouse wheel event is triggered, you can then implement a zoom behavior in the ChartPanAndZoomBehavior class. This documentation will help you create the behavior you are looking for. Notice in the XAML example in the documentation leverages <telerik:ChartPanAndZoomBehavior>, you can set the X and Y zoom value independently.
Below is an example of how to insert an event handler for the Mouse Wheel into your control. I have this event inside my chartView control
<!-- Notice the event named MouseWheel, I have creatd an event handler named RadChart1_MouseWheel. Inside that event you have the logic to determine which direction the mouse wheel is traveling and then apply the appropriate zoom method -->
<
chart:RadChart
x:Name
=
"RadChart1"
ItemsSource
=
"{Binding Data}"
UseDefaultLayout
=
"False"
MouseWheel
=
"RadChart1_MouseWheel"
>
<!-- all you chart's stuff in here -->
</
chart:RadChart
>
I hope this helps you achieve what you are trying to do. If you need any additional help, reply with some specifics on what you want to happen. Also if you include the code, it will help me come up with a solution for you quicker.
Good Luck!
Lancelot
Thanks for rescuing us. :D
I had done zoom out on radchart but because of one other feature I needed and that ChartView had i moved to it.
As about mouse wheel I had already noticed that I would have to use "MouseWheel". However I would like if possible to expand a bit more. Which property would I have to control in order of doing zoom out/in with wheel? Is it possible to show a demo with it?
Thanks
You should be able to extract what you need from the code below, if not, I have placed a link to the example at the end of this post.
public partial class MainPage : UserControl
{
public MainPage()
{
InitializeComponent();
var data = new List<
SomeInfo
>();
Random r = new Random();
for (int i = 0; i <
300
; i++)
{
data.Add(new SomeInfo(i, r.Next(0, 100)));
}
this.chartView.Series[0]
.ItemsSource
=
data
;
}
private void RadCartesianChart_MouseWheel(object sender, MouseWheelEventArgs e)
{
var
currentZoom
=
this
.chartView.Zoom;
if (e.Delta > 0)
{
currentZoom.Width *= 1.1;
this.chartView.Zoom = currentZoom;
}
else
{
if (currentZoom.Width/1.1 >= 1)
{
currentZoom.Width /= 1.1;
this.chartView.Zoom = currentZoom;
}
else if (Math.Round(currentZoom.Width, 1)/ 1.1 == 1)
{
currentZoom.Width = 1;
this.chartView.Zoom = currentZoom;
}
}
}
}
public class SomeInfo
{
public int XVal { get; set; }
public int YVal { get; set; }
public SomeInfo(int x, int y)
{
this.XVal = x;
this.YVal = y;
}
}
If you need the entire example application, you can download it from here (remember to "unblock" the zipped folder before extracting it or you wont be able to use the DLLs). If you havent done that before, all you need to do is right-click on the compressed folder and select "unblock" at the bottom.
Good Luck,
Lancelot
I just have one more request if I may.
On example you gave zoom is performed without looking at where is focus. What should I have in mind when performing zoom so I don't get lost on chart?... I mean my chart focus is set on x=7. I want that my zoom to be performed with focus on that point...
Can it be achieved?
Thanks "Sir".
If the user hasnt already clicked on any part of the chart then I would make sure it zooms into the center of what is currently in the view. However, if the user has clicked on a particular part of the chart, I would get the value of where the cursor is and use that as the center of your zoom. This way your app will remain intuitive and zoom where the user expects it to.
If there is no selected value by the user, get the difference between the lowest visible value and highest visible value, divide by 2 and add it to the bottom number. This will give you a center point to zoom in on. For example, lets say the lowest visible x value is 50 and the highest visible x value is 100, you'll want the center of the zoom to be at 75. If your currently visible chart section looked like this:
|50---------------------------------------------------------------------100|
You know the middle is 75 (because 100-50 = 25, then add 25 to the bottom number, 50 + 25 = 75), so use that to zoom in on. Otherwise always choose the user's selected x value.
Good Luck,
Lancelot
I implemented the http://demos.telerik.com/silverlight/#Chart/ZoomScroll example
But here ZoomOut button is disabled in the beginning, it is only activated when we click on ZoomIn.
But my scenario is, to ZoomIn I am dragging the chartwith mousedown and selecting the area.
I wnat to ZoomOut when a button is clicked.
Thanks in Advance,
You are only able to zoom out to the max value you have set in your chart. Using the FirstLook example you referred to, the chart has the zoom out button disabled because there is no way to zoom out further.
The chart goes from 11/7/1928 to 11/7/2013, and you see the scroll bar is fully stretched out. Go and zoom in now, the chart shows a smaller segment of the max values, therefore it can zoom out.
In your scenario, you said that you will be zooming in with a mouse selection. The example chart lets you do that. Notice when you zoom in with the section, the zoom out button is now enabled.
Could you provide me with some details of what you are trying to do and I can help write something custom for you.
Lancelot
Please find the code I am using:
.Xaml
<
telerik:ChartArea.ZoomScrollSettingsX>
<telerik:ZoomScrollSettings ScrollMode="ScrollAndZoom"
MinZoomRange="{Binding MinZoomRange, Mode=TwoWay}"
RangeEnd ="{Binding RangeEnd, Mode=TwoWay}"
RangeStart ="{Binding RangeStart, Mode=TwoWay}" />
</telerik:ChartArea.ZoomScrollSettingsX>
<telerik:RadButton Height="18" Width="20" BorderThickness="0" Margin="100,0,0,0" Name="btnZoomOut" Command="{Binding ZoomOutCommand}">
<Image x:Name = "imgZoomOut" Source="Images/ZoomOut.jpg" Width="15" Margin="0,0,2,0" ToolTipService.ToolTip="Chart ZoomOut"></Image>
</telerik:RadButton>
I am using a View.cs ,
using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using Telerik.Windows.Controls.Charting;
using Telerik.Windows.Controls;
using System.Collections.Generic;
using System.ComponentModel;
namespace SODANORTEL
{
public class View:INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
ICommand _zoomInCommand;
public ICommand ZoomInCommand
{
get
{
if (_zoomInCommand == null)
{
_zoomInCommand = new DelegateCommand(ZoomIn, CanZoomIn);
}
return _zoomInCommand;
}
}
ICommand _zoomOutCommand;
public ICommand ZoomOutCommand
{
get
{
if (_zoomOutCommand == null)
{
_zoomOutCommand = new DelegateCommand(ZoomOut, CanZoomOut);
}
return _zoomOutCommand;
}
}
private double _MaxZoomRange;
public double MaxZoomRange
{
get { return _MaxZoomRange; }
set
{
{
_MaxZoomRange = value;
OnPropertyChanged("MaxZoomRange");
}
}
}
//private double _Range;
public double Range
{
get { return RangeEnd - RangeStart; }
}
private double _RangeEnd;
public double RangeEnd
{
get { return _RangeEnd; }
set
{
{
_RangeEnd = value;
OnPropertyChanged("RangeEnd");
}
}
}
private double _RangeStart;
public double RangeStart
{
get { return _RangeStart; }
set
{
{
_RangeStart = value;
OnPropertyChanged("RangeStart");
}
}
}
private double _MinZoomRange;
public double MinZoomRange
{
get { return _MinZoomRange; }
set
{
{
_MinZoomRange = value;
OnPropertyChanged("MinZoomRange");
}
}
}
public void OnPropertyChanged(string propertyName)
{
if (this.PropertyChanged != null)
{
this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
private List<DataObject> _ItemsSource;
public List<DataObject> ItemsSource
{
get { return _ItemsSource; }
set
{
{
_ItemsSource = value;
OnPropertyChanged("ItemsSource");
}
}
}
//
// Summary:
// Gets or sets the scroll mode.
public ScrollMode ScrollMode { get; set; }
//
// Summary:
// Gets or sets the slider selection end.
public double SliderSelectionEnd { get; set; }
//
// Summary:
// Gets or sets the slider selection start.
public double SliderSelectionStart { get; set; }
public void ZoomIn(object parameter)
{
double zoomCenter = RangeStart + (Range / 2);
double newRange = Math.Max(MinZoomRange, Range) / 2;
RangeStart = Math.Max(0, zoomCenter - (newRange / 2));
RangeEnd = Math.Min(1, zoomCenter + (newRange / 2));
((DelegateCommand)_zoomInCommand).InvalidateCanExecute();
((DelegateCommand)_zoomOutCommand).InvalidateCanExecute();
}
public bool CanZoomIn(object parameter)
{
return Range > MinZoomRange;
}
public void ZoomOut(object parameter)
{
double zoomCenter = RangeStart + (Range / 2);
double newRange = Math.Min(1, Range) * 2;
if (zoomCenter + (newRange / 2) > 1)
zoomCenter = 1 - (newRange / 2);
else if (zoomCenter - (newRange / 2) < 0)
zoomCenter = newRange / 2;
RangeStart = Math.Max(0, zoomCenter - newRange / 2);
RangeEnd = Math.Min(1, zoomCenter + newRange / 2);
((DelegateCommand)_zoomInCommand).InvalidateCanExecute();
((DelegateCommand)_zoomOutCommand).InvalidateCanExecute();
}
public bool CanZoomOut(object parameter)
{
return Range < 1d;
}
public View()
{
MinZoomRange = 0.001;
//Range = 1.0;
RangeEnd = 1.0;
RangeStart = 0.0;
var dataSource = new List<DataObject>();
for (int i = 0; i < 10; i++)
{
dataSource.Add(new DataObject() { Date = DateTime.Today.AddDays(i), Value_data = i });
};
ItemsSource = dataSource;
}
private ChartArea _chartArea;
public ChartArea ChartArea
{
get
{
return this._chartArea;
}
set
{
this._chartArea = value;
}
}
}
}
Thanks in Advance,
You followed the example very well, but there is one thing you missed to do. You need to handle the DataBound event of RadChart and call the InvalidateCanExecute method for the two commands. This event is raised when you do some selection and respectively zoom.
All the best,
Explore the entire Telerik portfolio by downloading the Ultimate Collection trial package. Get it now >>
Thank you for the explanation, but how exactly can we control the focus when zooming in on the location where the mousepointer is ? I assume we need to adapt the panning offset. Which formula would we need to use ? Or is there another way of doing this more easy?
---
Ok, in the meantime I found out myself. Thought I share my code for those who are interested:
private
void
OnMouseWheel(
object
sender, MouseWheelEventArgs e)
{
// start coordinates of plot
var chartOffsetX = _chart.PanOffset.X + _chart.PlotAreaClip.X;
var chartOffsetY = _chart.PanOffset.Y + _chart.PlotAreaClip.Y;
// translated coordinates
var currentMousePosition = e.GetPosition(_chart);
currentMousePosition.X -= (chartOffsetX + _chart.PanOffset.X);
currentMousePosition.Y -= (chartOffsetY + _chart.PanOffset.Y);
// store current zoom and initialize new zoom
var currentZoom = _chart.Zoom;
var newZoom =
new
Size(currentZoom.Width, currentZoom.Height);
// calculate new zoom
if
(e.Delta > 0)
{
newZoom.Width *= 1.2;
newZoom.Height *= 1.01;
}
else
{
if
(newZoom.Width / 1.2 >= 1)
{
newZoom.Width /= 1.2;
}
else
if
(Math.Round(newZoom.Width, 1) / 1.2 == 1)
{
newZoom.Width = 1;
}
if
(newZoom.Height / 1.01 >= 1)
{
newZoom.Height /= 1.01;
}
else
if
(Math.Round(newZoom.Height, 1) / 1.01 == 1)
{
newZoom.Height = 1;
}
}
// calculate new mouseposition
var newMousePosition =
new
Point(currentMousePosition.X / currentZoom.Width * newZoom.Width,
currentMousePosition.Y / currentZoom.Height * newZoom.Height);
// apply zoom
_chart.Zoom = newZoom;
// calculate new pan offset
_chart.PanOffset =
new
Point(_chart.PanOffset.X - (newMousePosition.X - currentMousePosition.X),
_chart.PanOffset.Y - (newMousePosition.Y - currentMousePosition.Y));
}