Get Children from ListBox не может получить детей, которые не были просмотрены

У меня есть список в WPF, как следующий XAML. Он полон ListBoxItems, которые имеют флажок и метку внутри них. Один из моих пунктов вверху - это опция "выбрать все". Когда я нажимаю на опцию select all, у меня появляется обработчик, который перебирает все элементы списка, и он должен проверять все флажки на всех остальных дочерних элементах списка. Проблема в том, что он выполняет только видимые дочерние элементы, и когда он попадает в невидимые элементы списка, VisualTreeHelper, кажется, возвращает нуль при поиске объектов определенного типа (например, CheckBox). Кажется, что VisualTreeHelper, кажется, здесь проблематично. Я использую это неправильно? Любая помощь приветствуется. Еще одна деталь - если я прокручиваю и просматриваю все элементы списка хотя бы один раз, все работает нормально.

MJ

XAML - простой список с множеством детей (для краткости отображается только 1-й ребенок)

    <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# - две функции, первая - это вспомогательный метод, который обходит дерево объектов с помощью VisualTreeHelper (я нашел это на каком-то сайте). Вторая функция - обработчик щелчков для элемента списка "Выбрать все". Он перебирает все дочерние элементы и пытается установить все флажки.

    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);
                    }
                }
            }

        }

    }

1 ответ

Решение

Те визуальные методы ходьбы по дереву, плавающие повсюду, являются чумой. Вам почти никогда не нужно ничего из этого.

Просто свяжите ItemsSource в список объектов, содержащих свойства для CheckBoxes создать шаблон данных (ItemTemplate) и связать это свойство с CheckBox, В коде просто перебрать коллекцию, связанную с ItemsSource и установить porperty.

Другие вопросы по тегам