繁体   English   中英

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

[英]WPF accessing scrollviewer of a listview codebehind

我需要从代码隐藏访问列表视图的滚动查看器。 这是我的列表视图的定义

<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>

我怎样才能获得滚动查看器?

谢谢

安德烈亚

有几种方法可以获取ScrollViewer 最简单的解决方案是获取ListView的第一个孩子的第一个孩子。 这意味着像这个答案中描述的那样在这个 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;

第二种方法是扫描所有孩子的递归以找到 ScrollViewer。 这在马特汉密尔顿在这个问题的回答中有所描述。 您可以简单地使用此函数来获取ScrollViewer

ScrollViewer scrollViewer = GetChildOfType<ScrollViewer>(mylistview);

第二个解决方案更通用,如果编辑了ListView的模板,也可以使用。

使用 VisualTreeHelper 类访问任何子控件。

您的案例的伪代码:

 //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,但它是一个附加属性和附加属性,您可以这样设置: 如何在代码后面访问附加属性?

我还建议使用 CollectionChanged 事件。 在此代码中,在加载视图模型后,将 CollectionChanged 事件处理程序添加到代码隐藏中。 然后,每次集合更改时,我们都会滚动到列表视图的底部。 这里有一个重要的点。 当我们的事件开始触发时,列表视图的滚动查看器子级可能尚未完全呈现。 因此,如果我们尝试使用 VisualTreeHelper.GetChild 方法,我们将得到异常。 因此,我们必须首先尝试获取滚动查看器,然后如果尚不可用则忽略其定位。

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();
            }
        }
    }


    

LayoutUpdated之后应该可以访问 Listview 的 ScrollViewer 。 您可以挂钩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