Когда создаются элементы ListBoxItem для ListBox?

У меня есть ListBox, который я привязываю к ItemsSource, например:

var foos = new ObservableCollection<Foo> { foo1, foo2, foo3 };
var listBox = new ListBox { ItemsSource = _foos };

Теперь я хочу сразу же выполнить некоторые операции с ListBoxItems, в котором содержатся элементы, но, похоже, они не создаются сразу. Они? Есть ли какое-то событие, которое я могу прослушать, чтобы получить уведомление, или я просто пытаюсь получить ListBoxItem неверным способом? Я делаю это так (и убедился, что он работает где-то, я знаю, что ListBox "готов"):

var lbi = listBox.ItemContainerGenerator.ContainerFromItem(foo1) as ListBoxItem;

Обратите внимание, что это делается в модульном тесте, поэтому я предполагаю, что ListBox никогда не отображается. Поэтому не создаются ListBoxItems? И могу ли я каким-то образом вручную запустить создание ListBoxItems?


person stiank81    schedule 10.09.2010    source источник


Ответы (1)


Создание элементов выполняется асинхронно, и в зависимости от панели может случиться так, что она вообще не создается (виртуализация). Событие, которое вы ищете: _ 1_. Выполните поиск в Google на SO, вы найдете множество примеров. Однако непосредственный поиск предметов и работа с ними могут оказаться сложными.

Вот очень хорошая статья, подробно обсуждает создание предметов. Также ищите предка -статья .

Кстати: рекомендую посмотреть MVVM-паттерн. Хотя вы теряете немного времени на его изучение (не сравнимо со временем на изучение WPF), это сэкономит вам много времени. Здесь вы найдете ссылку на видео от Джейсона Долинджера, которое дает вам отличную отправную точку.

Обновление:

Как и было обещано в комментарии, здесь есть функция для поиска в визуальном дереве (можно использовать только при выключенной виртуализации).

void FindChildFrameworkElementsOfType<T>(DependencyObject parent,IList<T> list) where T: FrameworkElement{             
    DependencyObject child; 
    for(int i=0;i< VisualTreeHelper.GetChildrenCount(parent);i++){             
        child = VisualTreeHelper.GetChild(parent, i); 
        if (child is T) { 
            list.Add((T)child); 
        } 
        FindChildFrameworkElementsOfType<T>(child,list); 
    } 
} 
person HCL    schedule 10.09.2010
comment
Спасибо. Загляну в статьи и попробую использовать событие StatusChanged. Я уже использую MVVM, и видео действительно отличное. Однако в этом случае мне нужно перейти к деталям модульных тестов настраиваемого элемента управления, наследующего ListBox, над которым я работаю. - person stiank81; 10.09.2010
comment
@ stiank81: Если в ваших списках мало элементов, вы можете отключить виртуализацию с помощью VirtualizingStackPanel.IsVirtualizing = False в ListBox. Для небольших наборов данных это не будет проблемой. В зависимости от вашего модульного теста вы можете отключить виртуализацию также только для модульного теста. - person HCL; 10.09.2010
comment
Да, я хотел сделать это только для модульных тестов, но не похоже, чтобы я мог это сделать из кода. В нем говорится, что это частная собственность, но почему тогда я могу получить к ней доступ из xaml? Есть идеи, могу ли я каким-то образом вызвать это из кода? - person stiank81; 10.09.2010
comment
Статья действительно была интересной! Спасибо! Это многое объясняет, но все же оставляет у меня проблемы ... Пытался использовать событие ItemContainerGenerator.StatusChanged и ждал его выполнения, прежде чем продолжить, но оно никогда не запускается в моих модульных тестах. В любом случае я могу запустить генерацию вручную? .. - person stiank81; 10.09.2010
comment
@ stiank81: попробуйте yourListBox.SetValue (VirtualizingStackPanel.IsVirtualizing, false) или VirtualizingStackPanel.SetIsVirtualizing (yourListBox, false) - person HCL; 10.09.2010
comment
Второй вариант работает для деактивации виртуализации, но по-прежнему нет ListBoxItems и не срабатывает StatusChanged .. +1 кстати .. - person stiank81; 10.09.2010
comment
Другая возможность получить Items - через VisualTreeHelper. Если виртуализация отключена, все элементы должны быть доступны, и вы можете получить их через нее. Я расширю свой ответ ... - person HCL; 10.09.2010
comment
@ stiank81: я никогда не делал модульных тестов для WPF. Вы уверены, что весь рендеринг и создание элементов выполняется в рамках вашего теста? - person HCL; 10.09.2010
comment
Ну, похоже, этого не происходит ... Я создаю объект WPF в потоке STA, но это все на самом деле. Полагаю, он не отображается, и поэтому контейнеры никогда не создаются? Вы знаете, могу ли я что-нибудь сделать, чтобы вызвать рендеринг или что-то в этом роде? .. - person stiank81; 10.09.2010
comment
Вы можете попробовать использовать RenderTargetBitmap для создания изображения из вашего Visual, возможно, это запустит создание. msdn.microsoft.com/en-us/ библиотека / - person HCL; 10.09.2010