none
DataGrid如何在mvvm模式下绑定ScrollBar RRS feed

  • 问题

  • 例如如下datagrid,如何实现滚动条滚动到选中的row

                    <DataGrid HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Auto" Name="datagrid" CanUserAddRows="False" CanUserDeleteRows="False" AutoGenerateColumns="False" HeadersVisibility="Column" ItemsSource="{Binding Items}">
                        <DataGrid.Resources>
                            <Style TargetType="DataGridRow">
                                <Setter Property="IsSelected"  Value="{Binding IsSelected}" />
                            </Style>
                        </DataGrid.Resources>
                            <DataGridTextColumn Header="Location" Binding="{Binding Location,UpdateSourceTrigger=PropertyChanged}" Width="*"/>
                            <DataGridTextColumn Header="Suffix" Binding="{Binding Suffix,UpdateSourceTrigger=PropertyChanged}" Width="*"/>
                        </DataGrid.Columns>
                    </DataGrid>

    2016年6月28日 7:49

答案

  • 您好 Neo Xiao,

    DataGrid没有提供position属性可以供我们绑定。我们可以创建附加属性用来绑定。当这个附加属性发生改变的时候我们可以调用ScrollViewer的ScrollToVerticalOffset方法来改变ScrollView postisiond的位置。下面的示例代码供您参考。

    public static class ScrollViewerBinding
    {
        #region VerticalOffset attached property
    
        public static double GetVerticalOffset(DependencyObject depObj)
        {
            return (double)depObj.GetValue(VerticalOffsetProperty);
        }
    
        public static void SetVerticalOffset(DependencyObject depObj, double value)
        {
            depObj.SetValue(VerticalOffsetProperty, value);
        }
    
        public static readonly DependencyProperty VerticalOffsetProperty =
            DependencyProperty.RegisterAttached("VerticalOffset", typeof(double),
            typeof(ScrollViewerBinding), new PropertyMetadata(0.0, OnVerticalOffsetPropertyChanged));
    
        #endregion
    
        private static readonly DependencyProperty VerticalScrollBarProperty = DependencyProperty.RegisterAttached("VerticalScrollBar", typeof(ScrollBar),
                typeof(ScrollViewerBinding), new PropertyMetadata(null));
    
        private static void OnVerticalOffsetPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            ScrollViewer sv = d as ScrollViewer;
            if (sv != null)
            {
                // check whether we have a reference to the vertical scrollbar
                if (sv.GetValue(VerticalScrollBarProperty) == null)
                {
                    // if not, handle LayoutUpdated, which will be invoked after the
                    // template is applied and extract the scrollbar
                    sv.LayoutUpdated += (s, ev) =>
                    {
                        if (sv.GetValue(VerticalScrollBarProperty) == null)
                        {
                            GetScrollBarsForScrollViewer(sv);
                        }
                    };
                }
                else
                {
                    // update the scrollviewer offset
                    sv.ScrollToVerticalOffset((double)e.NewValue);
                }
            }
        }
    
        private static void GetScrollBarsForScrollViewer(ScrollViewer scrollViewer)
        {
            ScrollBar scroll = GetScrollBar(scrollViewer, Orientation.Vertical);
            if (scroll != null)
            {
                // save a reference to this scrollbar on the attached property
                scrollViewer.SetValue(VerticalScrollBarProperty, scroll);
    
                // scroll the scrollviewer
                scrollViewer.ScrollToVerticalOffset(
                  ScrollViewerBinding.GetVerticalOffset(scrollViewer));
    
    
                // handle the changed event to update the exposed VerticalOffset
                scroll.ValueChanged += (s, e) =>
                {
                    SetVerticalOffset(scrollViewer, e.NewValue);
                };
            }
        }
    
        private static ScrollBar GetScrollBar(FrameworkElement fe, Orientation orientation)
        {
            return GetVisualChild<ScrollBar>(fe);
    
        }
    
        private static T GetVisualChild<T>(DependencyObject parent) where T : Visual
        {
            T child = default(T);
            int numVisuals = VisualTreeHelper.GetChildrenCount(parent);
            for (int i = 0; i < numVisuals; i++)
            {
                Visual v = (Visual)VisualTreeHelper.GetChild(parent, i);
    
                child = v as T;
    
                if (child == null)
                {
                    child = GetVisualChild<T>(v);
                }
                if (child != null)
                {
                    break;
                }
            }
            return child;
        }
    }

    有了这个类之后,我们就可以把它的附加属性附加到别的控件上了。

    <ScrollViewer
        local:ScrollViewerBinding.VerticalOffset="{Binding YPosition, Mode=TwoWay}"
        local:ScrollViewerBinding.HorizontalOffset="{Binding XPosition, Mode=TwoWay}">
    </ScrollViewer>
    Best Regards,
    Li Wang

    We are trying to better understand customer views on social support experience, so your participation in this interview project would be greatly appreciated if you have time. Thanks for helping make community forums a great place.
    Click HERE to participate the survey.

    2016年7月10日 7:47

全部回复

  • 您好 Neo Xiao,

    >>"例如如下datagrid,如何实现滚动条滚动到选中的row:"

    DataGrid提供了ScrollIntoView方法,可以将滚动条滚动到对应的行。我们可以注册DataGrid的Loaded方法,然后使用ScrollIntoView方法即可。

    private void dataGrid_Loaded(object sender, RoutedEventArgs e)
    {
        dataGrid.ScrollIntoView(dataGrid.SelectedItem);
    }
    Best Regards,
    Li Wang

    We are trying to better understand customer views on social support experience, so your participation in this interview project would be greatly appreciated if you have time. Thanks for helping make community forums a great place.
    Click HERE to participate the survey.

    2016年6月30日 5:40
  • 这种办法我知道,我是问的在mvvm模式下如何绑定scroll的位置
    2016年7月1日 7:54
  • 您好 Neo Xiao,

    DataGrid没有提供position属性可以供我们绑定。我们可以创建附加属性用来绑定。当这个附加属性发生改变的时候我们可以调用ScrollViewer的ScrollToVerticalOffset方法来改变ScrollView postisiond的位置。下面的示例代码供您参考。

    public static class ScrollViewerBinding
    {
        #region VerticalOffset attached property
    
        public static double GetVerticalOffset(DependencyObject depObj)
        {
            return (double)depObj.GetValue(VerticalOffsetProperty);
        }
    
        public static void SetVerticalOffset(DependencyObject depObj, double value)
        {
            depObj.SetValue(VerticalOffsetProperty, value);
        }
    
        public static readonly DependencyProperty VerticalOffsetProperty =
            DependencyProperty.RegisterAttached("VerticalOffset", typeof(double),
            typeof(ScrollViewerBinding), new PropertyMetadata(0.0, OnVerticalOffsetPropertyChanged));
    
        #endregion
    
        private static readonly DependencyProperty VerticalScrollBarProperty = DependencyProperty.RegisterAttached("VerticalScrollBar", typeof(ScrollBar),
                typeof(ScrollViewerBinding), new PropertyMetadata(null));
    
        private static void OnVerticalOffsetPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            ScrollViewer sv = d as ScrollViewer;
            if (sv != null)
            {
                // check whether we have a reference to the vertical scrollbar
                if (sv.GetValue(VerticalScrollBarProperty) == null)
                {
                    // if not, handle LayoutUpdated, which will be invoked after the
                    // template is applied and extract the scrollbar
                    sv.LayoutUpdated += (s, ev) =>
                    {
                        if (sv.GetValue(VerticalScrollBarProperty) == null)
                        {
                            GetScrollBarsForScrollViewer(sv);
                        }
                    };
                }
                else
                {
                    // update the scrollviewer offset
                    sv.ScrollToVerticalOffset((double)e.NewValue);
                }
            }
        }
    
        private static void GetScrollBarsForScrollViewer(ScrollViewer scrollViewer)
        {
            ScrollBar scroll = GetScrollBar(scrollViewer, Orientation.Vertical);
            if (scroll != null)
            {
                // save a reference to this scrollbar on the attached property
                scrollViewer.SetValue(VerticalScrollBarProperty, scroll);
    
                // scroll the scrollviewer
                scrollViewer.ScrollToVerticalOffset(
                  ScrollViewerBinding.GetVerticalOffset(scrollViewer));
    
    
                // handle the changed event to update the exposed VerticalOffset
                scroll.ValueChanged += (s, e) =>
                {
                    SetVerticalOffset(scrollViewer, e.NewValue);
                };
            }
        }
    
        private static ScrollBar GetScrollBar(FrameworkElement fe, Orientation orientation)
        {
            return GetVisualChild<ScrollBar>(fe);
    
        }
    
        private static T GetVisualChild<T>(DependencyObject parent) where T : Visual
        {
            T child = default(T);
            int numVisuals = VisualTreeHelper.GetChildrenCount(parent);
            for (int i = 0; i < numVisuals; i++)
            {
                Visual v = (Visual)VisualTreeHelper.GetChild(parent, i);
    
                child = v as T;
    
                if (child == null)
                {
                    child = GetVisualChild<T>(v);
                }
                if (child != null)
                {
                    break;
                }
            }
            return child;
        }
    }

    有了这个类之后,我们就可以把它的附加属性附加到别的控件上了。

    <ScrollViewer
        local:ScrollViewerBinding.VerticalOffset="{Binding YPosition, Mode=TwoWay}"
        local:ScrollViewerBinding.HorizontalOffset="{Binding XPosition, Mode=TwoWay}">
    </ScrollViewer>
    Best Regards,
    Li Wang

    We are trying to better understand customer views on social support experience, so your participation in this interview project would be greatly appreciated if you have time. Thanks for helping make community forums a great place.
    Click HERE to participate the survey.

    2016年7月10日 7:47
  • Thank u
    2016年8月16日 0:27