Search code examples
c#wpfscrollviewer

WPF ScrollViewer + Grid and VisualTreeHelper.GetChildrenCount()


So I'm trying to get all controls from parent control (MainGrid) for it i use this:

            public static List<Visual> GetChildrens(Visual iParent, bool iRecursive)
            {
                List<Visual> result = new List<Visual>();

                iParent.Dispatcher.Invoke((Action)(() =>
                {
                    if (iRecursive)
                    {
                        Queue<Visual> toCheck = new Queue<Visual>();

                        toCheck.Enqueue(iParent);

                        while (toCheck.Count > 0)
                        {
                            for (int j = 0; j < VisualTreeHelper.GetChildrenCount(toCheck.Peek()); j++)
                            {
                                Visual childVisual = (Visual)VisualTreeHelper.GetChild(toCheck.Peek(), j);

                                toCheck.Enqueue(childVisual);
                                result.Add(childVisual);
                            }

                            toCheck.Dequeue();
                        }
                    }
                    else
                    {
                        for (int j = 0; j < VisualTreeHelper.GetChildrenCount(iParent); j++)
                        {
                            Visual childVisual = (Visual)VisualTreeHelper.GetChild(iParent, j);
                            result.Add(childVisual);
                        }
                    }
                }));

                return result;
            }

And it work with Grid, StackPanel, StackPanel + Grid, ScrollViewer but don't with ScrollViewer + Grids:

    <Grid x:Name="MainGrid">
        <ScrollViewer>
            <Grid>
                <Label Content="Pizza0" x:Name="Test0_Localize_Content" />
                <!--Don't work-->
            </Grid>
        </ScrollViewer>

        <ScrollViewer x:Name="SVName">
            <Grid>
                <Label Content="Pizza1" x:Name="Test1_Localize_Content" /> 
                <!--Don't work-->
            </Grid>
        </ScrollViewer>

        <ScrollViewer>
            <Label Content="Pizza0" x:Name="Test0_Localize_Content" />
            <!--Work-->
        </ScrollViewer>

        <Grid>
            <Grid>
                <Label Content="Pizza2" x:Name="Test2_Localize_Content" /> 
                <!--Work-->
            </Grid>
        </Grid>

        <StackPanel>
            <Grid>
                <Label Content="Pizza3" x:Name="Test3_Localize_Content" /> 
                <!--Work-->
            </Grid>
        </StackPanel>
    </Grid>

What i don't understand? (So to post my question "It looks like your post is mostly code; please add some more details") so: how i can fix it, what i don't understand it's WPF and c#.


Solution

  • The ScrollViewer control doesn't have a definition of children because it can only hold one element.

    To get the child of the ScrollViewer you have to check its Content.

    the easiest modify to your code is:

    while (toCheck.Count > 0)
    {
        if(toCheck.Peek() is ScrollViewer)  
        {
            ScrollViewer scroll = toCheck.Peek() as ScrollViewer;
            if(scroll.Content is not null)
            {
                toCheck.Enqueue(scroll.Content as Visual);
                result.Add(scroll.Content as Visual);
            }
        }
        else
        {
            for (int j = 0; j < VisualTreeHelper.GetChildrenCount(toCheck.Peek()); j++)
            {
                Visual childVisual = (Visual)VisualTreeHelper.GetChild(toCheck.Peek(), j);
    
                toCheck.Enqueue(childVisual);
                result.Add(childVisual);
            }
        }
    
        toCheck.Dequeue();
    }