1

具有一个 DataGrid 的视图和具有以下 功能的ViewModel

public  DependencyObject ScrollViewer(DependencyObject targetControl)
    {
        if (targetControl is ScrollViewer)
        {
            return targetControl;
        }

        for (int i = 0; i < VisualTreeHelper.GetChildrenCount(targetControl); i++)
        {
            var child = VisualTreeHelper.GetChild(targetControl, i);
            var result = ScrollViewer(child);
            if (result == null)
            {
                continue;
            }
            else
            {
                return result;
            }
        }
        return null;
    }

现在我想使用上述功能获取网格的滚动查看器。

var scrolViewer = ScrollViewer(dataGridID) as ScrollViewer;

如果我将数据网格 ID 作为参数传递。我会得到结果。但这在 MVVM 模式中是不可能的。有没有办法获得可视子数据网格?

4

1 回答 1

1

我创建了一个快捷Attached Property方式,可以让您坚持使用 MVVM 概念,还可以让您滚动到DataGrid. 它可以改进(例如,避免使用两个单独的属性并使用 anIValueConverter来决定如何滚动),但这应该会给你一个很好的起点。

首先,我们创建附加属性(一个用于滚动到底部,一个用于顶部)

public static class Scroller
{
     //Create the attached property and register it
     public static readonly DependencyProperty ScrollToBottomProperty =
        DependencyProperty.RegisterAttached("ScrollToBottom", typeof(bool), typeof(Scroller), new PropertyMetadata(false, ScrollToBottomPropertyChanged));


     //Create the get and set methods for the property
     public static bool GetScrollToBottom(DependencyObject obj)
     {
         return (bool)obj.GetValue(ScrollToBottomProperty);
     }

     public static void SetScrollToBottom(DependencyObject obj, bool value)
     {
         obj.SetValue(ScrollToBottomProperty, value);
     }


     //Get the control that you've attached this to (DataGrid in this case) and find its ScrollViewer 
     private static void ScrollToBottomPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
     {
         var scrollViewer = GetScrollViewer(d) as ScrollViewer;
         if (scrollViewer != null && (bool)e.NewValue)
         {
            //Use built in ScrollToBottom method to scroll to...well...the bottom :)
             scrollViewer.ScrollToBottom();
         }
     }


     //Same as above but for "ScrollToTop" method
     public static readonly DependencyProperty ScrollToTopProperty =
     DependencyProperty.RegisterAttached("ScrollToTop", typeof(bool), typeof(Scroller), new PropertyMetadata(false, ScrollToTopPropertyChanged));


     public static bool GetScrollToTop(DependencyObject obj)
     {
         return (bool)obj.GetValue(ScrollToTopProperty);
     }

     public static void SetScrollToTop(DependencyObject obj, bool value)
     {
         obj.SetValue(ScrollToTopProperty, value);
     }



     private static void ScrollToTopPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
     {
         var scrollViewer = GetScrollViewer(d) as ScrollViewer;

         if (scrollViewer != null && (bool)e.NewValue)
         {
             scrollViewer.ScrollToTop();
         }
     }


     //Your ScrollViewerMethod (I renamed it to GetScrollViewer for clarity)
     public static DependencyObject GetScrollViewer(DependencyObject targetControl)
     {
         if (targetControl is ScrollViewer)
         {
             return targetControl;
         }

         for (int i = 0; i < VisualTreeHelper.GetChildrenCount(targetControl); i++)
         {
             var child = VisualTreeHelper.GetChild(targetControl, i);
             var result = GetScrollViewer(child);
             if (result == null)
             {
                 continue;
             }
             else
             {
                 return result;
             }
         }
         return null;
     }
}

在您的 XAML 中,您需要添加相关的命名空间(相应地更改您的命名空间)

xmlns:custom="clr-namespace:ScrollExampleMVVM"

然后我们可以将属性附加到我们的DataGrid

<DataGrid custom:Scroller.ScrollToBottom="{Binding ScrollBottom}" custom:Scroller.ScrollToTop="{Binding ScrollTop}" ...?

在您的 ViewModel 中,您可以拥有公共ScrollBottomScrollTop属性

private bool _scrollBottom = false;
public bool ScrollBottom 
{
    get { return _scrollBottom; }
    set
    {
         _scrollBottom = value;                
         NotifyPropertyChanged("ScrollBottom");              
    }
}

private bool _scrollTop = false;
public bool ScrollTop
{
     get { return _scrollTop; }
     set
     {
          _scrollTop = value;
          NotifyPropertyChanged("ScrollTop");
     }
}

最后处理你的按钮(我猜你正在使用ICommands)来调用滚动

private void ScrollBottomCommand(object param)
{
    //Immediately set back to false so that it can be reused
    ScrollBottom = true;
    ScrollBottom = false;
}

private void ScrollTopCommand(object param)
{
    ScrollTop = true;
    ScrollTop = false;
}

那应该行得通。如前所述,您可能可以对其进行改进以避免重置代码,但希望这可以提供一个想法。

于 2013-03-30T13:55:26.807 回答