Search code examples
c#xamlwindows-phone-8longlistselector

Is there a way to jump to the ListHeader of a LongListSelector?


I'm working on a Windows Phone 8 application and I wanted to implement a button that would allow me to jump to the top of the ListHeader of a LongListSelector (The ListHeader contains some radio buttons that I'm using to filter content). Is there any way to do this?


Solution

  • In your button handler, use this method to get the ViewPortControl from the LongListSelector's template.

        public static T FindChild<T>(DependencyObject parent, string childName) where T : DependencyObject
        {
            // Confirm parent and childName are valid. 
            if (parent == null)
            {
                return null;
            }
    
            T foundChild = null;
    
            int childrenCount = VisualTreeHelper.GetChildrenCount(parent);
            for (int i = 0; i < childrenCount; i++)
            {
                DependencyObject child = VisualTreeHelper.GetChild(parent, i);
                // If the child is not of the request child type child
                var childType = child as T;
                if (childType == null)
                {
                    // recursively drill down the tree
                    foundChild = FindChild<T>(child, childName);
    
                    // If the child is found, break so we do not overwrite the found child. 
                    if (foundChild != null)
                    {
                        break;
                    }
                }
                else if (!string.IsNullOrEmpty(childName))
                {
                    var frameworkElement = child as FrameworkElement;
                    // If the child's name is set for search
                    if (frameworkElement != null && frameworkElement.Name == childName)
                    {
                        // if the child's name is of the request name
                        foundChild = (T)child;
                        break;
                    }
    
                    // Need this in case the element we want is nested
                    // in another element of the same type
                    foundChild = FindChild<T>(child, childName);
                }
                else
                {
                    // child element found.
                    foundChild = (T)child;
                    break;
                }
            }
    
            return foundChild;
        }
    

    Then use THIS to scroll to the top of the ViewPortControl.

    Usage:

    private void Button_OnClick(object sender, RoutedEventArgs e)
    {
        var viewPort = FindChild<ViewportControl>(yourLongListSelector, "ViewportControl");
        viewPort.SetViewportOrigin(new Point(0,0));
    }
    

    In case you're wondering where the ViewPortControl came from, here's the LongListSelector's style.

    <Style x:Key="LongListSelectorStyle1" TargetType="phone:LongListSelector">
            <Setter Property="Background" Value="Transparent"/>
            <Setter Property="Foreground" Value="{StaticResource PhoneForegroundBrush}"/>
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="phone:LongListSelector">
                        <Grid Background="{TemplateBinding Background}" d:DesignWidth="480" d:DesignHeight="800">
                            <VisualStateManager.VisualStateGroups>
                                <VisualStateGroup x:Name="ScrollStates">
                                    <VisualStateGroup.Transitions>
                                        <VisualTransition GeneratedDuration="00:00:00.5"/>
                                    </VisualStateGroup.Transitions>
                                    <VisualState x:Name="Scrolling">
                                        <Storyboard>
                                            <DoubleAnimation Duration="0" To="1" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="VerticalScrollBar"/>
                                        </Storyboard>
                                    </VisualState>
                                    <VisualState x:Name="NotScrolling"/>
                                </VisualStateGroup>
                            </VisualStateManager.VisualStateGroups>
                            <Grid Margin="{TemplateBinding Padding}">
                                <Grid.ColumnDefinitions>
                                    <ColumnDefinition Width="*"/>
                                    <ColumnDefinition Width="auto"/>
                                </Grid.ColumnDefinitions>
                                <ViewportControl x:Name="ViewportControl" HorizontalContentAlignment="Stretch" VerticalAlignment="Top"/>
                                <ScrollBar x:Name="VerticalScrollBar" Grid.Column="1" Margin="4,0,4,0" Opacity="0" Orientation="Vertical"/>
                            </Grid>
                        </Grid>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>