Get Children from ListBox cannot get children who have not been viewed.

I have a list in WPF, as in the following XAML. It is filled with ListBoxItems, which has a checkbox and a label inside them. One of my elements at the top is the “select all” option. When I click the Select All button, I have a handler that iterates through all the elements of the list, and it should check all the checkboxes for all the other children of the list. The problem is that it only makes visible child elements and when it falls into listboxitems invisible elements, VisualTreeHelper seems to return null when looking for objects of a certain type (e.g. CheckBox). VisualTreeHelper seems to be problematic here. Am I using this incorrectly? Any help appreciated. Another detail - if I scroll and scroll through all the elements of the list at least once, it works fine.

Mj

XAML - a simple list with a ton of children (only for the 1st child, displayed for brevity)

    <ListBox Grid.Row="0" Margin="0,0,0,0" Name="CharacterListBox">
        <ListBoxItem>
            <StackPanel Orientation="Horizontal">
                <CheckBox HorizontalAlignment="Center" VerticalAlignment="Center" Click="AllCharactersClicked"></CheckBox>
                <Label Padding="5">All Characters</Label>
            </StackPanel>
        </ListBoxItem>

C # - two functions, the first is a helper method that processes a tree of objects using VisualTreeHelper (I found this on some website). The second function is the click handler for the "select all" listboxitem. It iterates through all the children and tries to check all the checkboxes.

    private T FindControlByType<T>(DependencyObject container, string name) where T : DependencyObject
    {
        T foundControl = null;

        //for each child object in the container
        for (int i = 0; i < VisualTreeHelper.GetChildrenCount(container); i++)
        {
            //is the object of the type we are looking for?
            if (VisualTreeHelper.GetChild(container, i) is T && (VisualTreeHelper.GetChild(container, i).GetValue(FrameworkElement.NameProperty).Equals(name) || name == null))
            {
                foundControl = (T)VisualTreeHelper.GetChild(container, i);
                break;
            }
            //if not, does it have children?
            else if (VisualTreeHelper.GetChildrenCount(VisualTreeHelper.GetChild(container, i)) > 0)
            {
                //recursively look at its children
                foundControl = FindControlByType<T>(VisualTreeHelper.GetChild(container, i), name);
                if (foundControl != null)
                    break;
            }
        }

        return foundControl;
    }

    private void AllCharactersClicked(object sender, RoutedEventArgs e)
    {

        MainWindow.Instance.BadChars.Clear();

        int count = 0;
        foreach (ListBoxItem item in CharacterListBox.Items)
        {
            CheckBox cb = FindControlByType<CheckBox>(item, null);                
            Label l = FindControlByType<Label>(item, null);
            if (cb != null && l != null)
            {
                count++;
                cb.IsChecked = true;

                if (cb.IsChecked == true)
                {
                    string sc = (string)l.Content;
                    if (sc.Length == 1)
                    {
                        char c = Char.Parse(sc);
                        MainWindow.Instance.BadChars.Add(c);
                    }
                }
            }

        }

    }
0
source share
1 answer

These visual tree techniques floating around everywhere are a plague. You almost never need it.

Just bind ItemsSourceto the list of objects containing properties for CheckBoxes, create ( ItemTemplate) and bind to the property CheckBox. In the code, just ItemsSourceiterate over the collection bound to and specify porperty.

+3
source

All Articles