locked
XAML ListView ScrollViewer.ScrollableHeight is zero

    Question

  • Another possible tile is "How do you get the ScrollViewer for a ListView"

    Since the Windows.UI.Xaml.ListView class does not have a ScrollViewer property I use the following code to find it:

    ScrollViewer scrollViewer = null;
    for (UIElement vis = ctl; vis != null; vis = VisualTreeHelper.GetParent(vis) as UIElement)
      if ((scrollViewer = vis as ScrollViewer) != null)
        break;
    if (scrollViewer == null) return false;

    I don't know if this retrieves the correct ScrollViewer, but I get the following properties:

    The ListView (aka "ctl" in the code above) has 279 items, the Surface RT device I am testing on shows 14 items in the ScrollViewer viewport.

    ScrollViewer.ExtentHeight = 768

    ScrollViewer.ViewportHeight = 768

    ScrollViewer.ScrollabeHeight = 0

    Also what I'm getting is the width is of the extents and viewport are 1366 which is the pixel resolution of the RT. i.e. 1366 by 768. Obviously, this is not the ScrollViewer I'm looking for.


    Friday, March 7, 2014 3:48 AM

Answers

  • You can subclass the ScrollViewer and use the Control.GetTemplateChild method .

    You can find the ListView's template by creating a copy with EditTemplate... or in the ListView styles and templates documentation. It's ScrollViewer is named "ScrollViewer" (tricky, huh? :) )

    The ScrollViewer isn't very deep in the template so you won't need to recurse far if you'd prefer that method (and you could do this iteratively rather than recursing).

    --Rob

    Friday, March 7, 2014 5:50 AM
    Owner

All replies

  • Ok, I realize is not good "forums" netiquette to respond to your own post, but I see now what the problem is with the above code, but I still have not solved the problem.

    The above code calls VisualTreeHelper.GetParent, obvisously I need to call GetChild. The problem with GetChild is that it must be called recursively since it takes a Dependency object and a child index. More important is the idea of arbitrarily searching through the tree and picking first thing you find is idiotic.

    So. The ScrollViewer is a member of the ControlTemplate. Is there a way to get the instance of a member of a ControlTemplate at runtime? 

    Thanks


    Friday, March 7, 2014 4:25 AM
  • You can subclass the ScrollViewer and use the Control.GetTemplateChild method .

    You can find the ListView's template by creating a copy with EditTemplate... or in the ListView styles and templates documentation. It's ScrollViewer is named "ScrollViewer" (tricky, huh? :) )

    The ScrollViewer isn't very deep in the template so you won't need to recurse far if you'd prefer that method (and you could do this iteratively rather than recursing).

    --Rob

    Friday, March 7, 2014 5:50 AM
    Owner
  • Thanks Rob,

    You help me out many times, but I just can't bring myself to mark your response as answered, for the following reasons:

    1) GetTemplateChild - For whatever reason that method is not visible to my ListView, I should care about that, for many reasons, but I don't. Mostly because I have no interest in subclassing anything. All I want is a reference to the ScrollViewer of an instantiated ListView.

    2) The solution is recursive. It is only iterative if you magically know that it is a child of the first child.

    Just my opinion, but - GetTemplateChild should be visible and should work, and not required any subclassing, it should just work.

    So. For what it's worth I am posting a solution.

    Major caveat - This code only works for Windows.Ui.Xaml Windows 8.1. It is not necessarily portable to WPF, Silverlight, and any other XAML based API or, for that matter,  Windows.Ui.Xaml version of Windows other than 8.1.

    UIElement dummy = VisualTreeHelper.GetChild(ctl, 0) as UIElement;
    int childCount = VisualTreeHelper.GetChildrenCount(dummy);
    ScrollViewer scrollViewer = null;
    for (int i = 0; i < childCount; ++i)
    {
    	scrollViewer = VisualTreeHelper.GetChild(dummy, i) as ScrollViewer;
    	if (scrollViewer != null) break;
    }
    if (scrollViewer == null) return false;

    After some thought, I changed my mind and marked Rob's answer as correct. Sometimes the truth ain't pretty, but you have to take what you can get. I have to say everything to do with runtime XAML seems like hacking to me, and feels very fragile in terms of binary compatibility. I hope this changes in future versions. 
    Saturday, March 8, 2014 5:26 AM