简体   繁体   English

WPF访问列表视图代码隐藏的滚动查看器

[英]WPF accessing scrollviewer of a listview codebehind

I need to access the scrollviewer of a listview from the codebehind.我需要从代码隐藏访问列表视图的滚动查看器。 here is the definition of my listview这是我的列表视图的定义

<ListView Grid.Row="1" ItemsSource="{Binding Path=SpecList, UpdateSourceTrigger=PropertyChanged}"  
                            Name="mylistview"
                            ItemTemplate="{StaticResource SpecElementTemplate}"
                            Background="{StaticResource EnvLayout}"
                            ScrollViewer.HorizontalScrollBarVisibility="Visible"
                            ScrollViewer.VerticalScrollBarVisibility="Disabled"
                            ItemContainerStyle="{StaticResource MyStyle}"
                            BorderBrush="Blue"
                            BorderThickness="20"
                            Margin="-2">
    <ListView.ItemsPanel>
        <ItemsPanelTemplate>
            <StackPanel Orientation="Horizontal" />
        </ItemsPanelTemplate>
    </ListView.ItemsPanel>
</ListView>

How can I get the scrollviewer?我怎样才能获得滚动查看器?

Thank you谢谢

Andrea安德烈亚

There are several ways to get the ScrollViewer .有几种方法可以获取ScrollViewer Simplest solution is to get the the first child of the first child of the ListView .最简单的解决方案是获取ListView的第一个孩子的第一个孩子。 This means get the Border and the ScrollViewer inside this Border like described in this answer :这意味着像这个答案中描述的那样在这个 Border 中获取BorderScrollViewer

// Get the border of the listview (first child of a listview)
Decorator border = VisualTreeHelper.GetChild(mylistview, 0) as Decorator;

// Get scrollviewer
ScrollViewer scrollViewer = border.Child as ScrollViewer;

A second way is to scan all childrens recursive to find the ScrollViewer.第二种方法是扫描所有孩子的递归以找到 ScrollViewer。 This is described in the answer by Matt Hamilton in this question .这在马特汉密尔顿在这个问题的回答中有所描述。 You can simply use this function to get the ScrollViewer .您可以简单地使用此函数来获取ScrollViewer

ScrollViewer scrollViewer = GetChildOfType<ScrollViewer>(mylistview);

This second solution is much more generic and will also work if the template of your ListView was edited.第二个解决方案更通用,如果编辑了ListView的模板,也可以使用。

Use VisualTreeHelper class to access any child control.使用 VisualTreeHelper 类访问任何子控件。

Psudeo code to your case:您的案例的伪代码:

 //Declare a scroll viewer object.
 ScrollViewer  sViewer = default(ScrollViewer );

 //Start looping the child controls of your listview.
 for (int i = 0; i < VisualTreeHelper.GetChildrenCount(YOUR_LISTVIEW_OBJECT.VisualParent ); i++)
 {
        // Retrieve child visual at specified index value.
        Visual childVisual = (Visual)VisualTreeHelper.GetChild(YOUR_LISTVIEW_OBJECT.VisualParent , i);

        ScrollViewer sViewer = childVisual as ScrollViewer;

        //You got your scroll viewer. Stop looping.
         if (sViewer != null)
         {
             break;
         }      
 }

我不知道您为什么要访问scrollviewer,但它是一个附加属性和附加属性,您可以这样设置: 如何在代码后面访问附加属性?

I also suggest using the CollectionChanged event.我还建议使用 CollectionChanged 事件。 In this code, the CollectionChanged event handler is added to the codebehind after the view model has been loaded.在此代码中,在加载视图模型后,将 CollectionChanged 事件处理程序添加到代码隐藏中。 Then, each time the collection changes we scroll to the bottom of the listview.然后,每次集合更改时,我们都会滚动到列表视图的底部。 Here is an important point.这里有一个重要的点。 The scrollviewer child of the list view might not yet be completely rendered when our events start firing.当我们的事件开始触发时,列表视图的滚动查看器子级可能尚未完全呈现。 Hence we will get exceptions if we try to use the VisualTreeHelper.GetChild method.因此,如果我们尝试使用 VisualTreeHelper.GetChild 方法,我们将得到异常。 So, we have to first attempt to get the scrollviewer and then ignore its positioning if it is not yet available.因此,我们必须首先尝试获取滚动查看器,然后如果尚不可用则忽略其定位。

private void ReceivedItems_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
    {
        // Make sure the items source property in the viewmodel has some items
        if (myViewModel.ReceivedItems.Count > 0)
        {
            var aScrollViewer = RcvdListView.GetChildOfType<ScrollViewer>();
            // Make sure the scrollviewer exists before trying to position it
            if (aScrollViewer != null)
            {
                aScrollViewer.ScrollToBottom();
            }
        }
    }


    

Listview's ScrollViewer should be accessible after LayoutUpdated .LayoutUpdated之后应该可以访问 Listview 的 ScrollViewer 。 You could hook on LayoutUpdated and then get if from Visual tree您可以挂钩LayoutUpdated ,然后从Visual tree获取 if

 private static void ListView_LayoutUpdated(object sender, EventArgs e)
 {
    var listview = (ListView)sender;
    var viewer = listview.GetFirstChildOfType<ScrollViewer>();
 }

public static T GetFirstChildOfType<T>(this DependencyObject dependencyObject) where T : DependencyObject
    {
      if (dependencyObject == null)
      {
        return null;
      }

      for (var i = 0; i < VisualTreeHelper.GetChildrenCount(dependencyObject); i++)
      {
        var child = VisualTreeHelper.GetChild(dependencyObject, i);

        var result = (child as T) ?? GetFirstChildOfType<T>(child);

        if (result != null)
        {
          return result;
        }
      }

      return null;
    }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM