WPF accessing scrollviewer of a listview codebehind
Asked Answered
U

4

5

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

Unmeaning answered 27/3, 2017 at 17:57 Comment(0)
R
7

There are several ways to get the ScrollViewer. Simplest solution is to get the the first child of the first child of the ListView. This means get the Border and the ScrollViewer inside this Border like described in 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;

A second way is to scan all childrens recursive to find the 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 = GetChildOfType<ScrollViewer>(mylistview);

This second solution is much more generic and will also work if the template of your ListView was edited.

Rencontre answered 27/3, 2017 at 18:26 Comment(1)
I'd love to know what the person who designed this was thinking! If Microsoft designed cars you'd probably have to open the boot and find a door open button in a hidden compartment in the boot to get in.Barfuss
A
1

Use VisualTreeHelper class to access any child control.

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;
         }      
 }
Antibaryon answered 27/3, 2017 at 18:26 Comment(0)
S
0

I also suggest using the CollectionChanged event. In this code, the CollectionChanged event handler is added to the codebehind after the view model has been loaded. 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. 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();
            }
        }
    }


    
Stalingrad answered 15/1, 2021 at 3:58 Comment(0)
W
0

Listview's ScrollViewer should be accessible after LayoutUpdated. You could hook on LayoutUpdated and then get if from Visual tree

 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;
    }
Witenagemot answered 30/3, 2021 at 16:12 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.