【问题标题】:WPF accessing scrollviewer of a listview codebehindWPF 访问列表视图代码隐藏的滚动查看器
【发布时间】:2021-03-31 00:12:12
【问题描述】:

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

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

如何获取滚动查看器?

谢谢

安德烈亚

【问题讨论】:

    标签: c# wpf listview code-behind scrollviewer


    【解决方案1】:

    有几种方法可以获取ScrollViewer。最简单的解决方案是获取ListView 的第一个孩子的第一个孩子。这意味着在此 Border 内获取 BorderScrollViewer,如中所述 this answer:

    // 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。 Matt Hamilton 在this question 的回答中对此进行了描述。你可以简单地使用这个函数来获取ScrollViewer

    ScrollViewer scrollViewer = GetChildOfType<ScrollViewer>(mylistview);
    

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

    【讨论】:

    • 我很想知道设计这个的人是怎么想的!如果是微软设计的汽车,你可能必须打开后备箱并在后备箱的隐藏隔间中找到一个开门按钮才能进入。
    【解决方案2】:

    使用 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;
             }      
     }
    

    【讨论】:

      【解决方案3】:

      我还建议使用 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();
                  }
              }
          }
      
      
          
      

      【讨论】:

        【解决方案4】:

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

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2011-10-27
          • 1970-01-01
          • 2018-05-16
          • 2015-03-02
          • 1970-01-01
          相关资源
          最近更新 更多