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.