Your Privacy Matters: We use our own and third-party cookies to improve your experience on our website. By continuing to use the website we understand that you accept their use. Cookie Policy
40
Selecting a range of data and sending the range to the ViewModel
posted

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

Parents
  • 30692
    Offline posted

    One way of approaching this would be to basically just hi-jack the zoom change and use it to determine
    selected 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

Reply Children