Is it possible to select a range of data in the data chart by dragging the mouse and then sending the data range to a bound method (viewmodel)?
Basically the functionality we need is similar to the "DragZoom" default interaction, but we want to replace the zoom operation with our own operation. Using the SeriesMouseLeftButtonDown/Up events does not work well since the start and end points are not directly over data points.
It would be great if we could get the behavoir of drawing the box as in DragZoom but opon completion just have the box boundaries sent to the viewmodel.
thanks
One way of approaching this would be to basically just hi-jack the zoom change and use it to determineselected axis range. You would, of course, need to be craftier if you wanted to be able to zoom or select.Let me know if this helps!The xaml:
<UserControl.Resources> <local:TestData x:Key="data1" /> </UserControl.Resources> <Grid x:Name="LayoutRoot" Background="White"> <Grid.RowDefinitions> <RowDefinition /> <RowDefinition Height="Auto"/> </Grid.RowDefinitions> <ig:XamDataChart Name="xamDataChart1" VerticalZoomable="True" HorizontalZoomable="True" > <ig:XamDataChart.Axes> <ig:CategoryXAxis x:Name="xAxis" ItemsSource="{StaticResource data1}" Label="{}{Label}"/> <ig:NumericYAxis x:Name="yAxis" /> </ig:XamDataChart.Axes> <ig:XamDataChart.Series> <ig:LineSeries x:Name="testLine" ItemsSource="{StaticResource data1}" XAxis="{Binding ElementName=xAxis}" YAxis="{Binding ElementName=yAxis}" ValueMemberPath="Value" /> </ig:XamDataChart.Series> </ig:XamDataChart> <StackPanel Grid.Row="1" Orientation="Horizontal" > <TextBlock Text="Selected: " /> <TextBlock Text="X: " /> <TextBlock Text="{Binding StartSelectionX}" /> <TextBlock Text="," /> <TextBlock Text="{Binding EndSelectionX}" /> <TextBlock Text="Y:" /> <TextBlock Text="{Binding StartSelectionY}" /> <TextBlock Text="," /> <TextBlock Text="{Binding EndSelectionY}" /> </StackPanel> </Grid>
And the code behind:
public partial class MainPage : UserControl, INotifyPropertyChanged { public MainPage() { InitializeComponent(); DataContext = this; SetBinding( AttemptedScaleProperty, new Binding("WindowRect") { Source = xamDataChart1 }); } public static readonly DependencyProperty AttemptedScaleProperty = DependencyProperty.Register( "AttemptedScale", typeof(Rect), typeof(MainPage), new PropertyMetadata( Rect.Empty, (o, e) => (o as MainPage).OnAttemptedScaleChanged(e))); public Rect AttemptedScale { get { return (Rect)GetValue(AttemptedScaleProperty); } set { SetValue(AttemptedScaleProperty, value); } } private Rect _selectedRect; private bool _recursing; private double _startSelectionX; public double StartSelectionX { get { return _startSelectionX; } set { _startSelectionX = value; if (PropertyChanged != null) { PropertyChanged( this, new PropertyChangedEventArgs("StartSelectionX")); } } } private double _endSelectionX; public double EndSelectionX { get { return _endSelectionX; } set { _endSelectionX = value; if (PropertyChanged != null) { PropertyChanged( this, new PropertyChangedEventArgs("EndSelectionX")); } } } private double _startSelectionY; public double StartSelectionY { get { return _startSelectionY; } set { _startSelectionY = value; if (PropertyChanged != null) { PropertyChanged( this, new PropertyChangedEventArgs("StartSelectionY")); } } } private double _endSelectionY; public double EndSelectionY { get { return _endSelectionY; } set { _endSelectionY = value; if (PropertyChanged != null) { PropertyChanged( this, new PropertyChangedEventArgs("EndSelectionY")); } } } private void OnAttemptedScaleChanged( DependencyPropertyChangedEventArgs e) { if ((Rect)e.NewValue != _selectedRect && (Rect)e.OldValue != Rect.Empty && !_recursing) { _selectedRect = (Rect)e.NewValue; _recursing = true; xamDataChart1.WindowRect = (Rect)e.OldValue; _recursing = false; Rect viewportRect = new Rect(0,0,1,1); CategoryXAxis x = xamDataChart1.Axes[0] as CategoryXAxis; NumericYAxis y = xamDataChart1.Axes[1] as NumericYAxis; StartSelectionX = x.GetUnscaledValue(0, _selectedRect, viewportRect); EndSelectionX = x.GetUnscaledValue(1, _selectedRect, viewportRect); StartSelectionY = y.GetUnscaledValue(0, _selectedRect, viewportRect); EndSelectionY = y.GetUnscaledValue(1, _selectedRect, viewportRect); } } public event PropertyChangedEventHandler PropertyChanged; } public class TestDataItem { public string Label { get; set; } public double Value { get; set; } } public class TestData : ObservableCollection<TestDataItem> { private static Random rand = new Random(); public TestData() { double curr = 0; for (int i = 0; i < 1000; i++) { if (rand.NextDouble() > .5) { curr += rand.NextDouble(); } else { curr -= rand.NextDouble(); } Add( new TestDataItem() { Label = i.ToString(), Value = curr }); } } }
-Graham