2010-07-20 4 views
1

У меня есть ListBox, и мне нужно, чтобы установить его ControlTemplate на виртуализацию WrapPanel который является классом, который расширяет VirtualizingPanel, используя стиль, который выглядит следующим образом:Почему ItemContainerGenerator возвращает null?

<Style TargetType="{x:Type ListBox}" x:Key="PhotoListBoxStyle"> 
       <Setter Property="Foreground" Value="White" /> 
       <Setter Property="Template"> 
        <Setter.Value> 
         <ControlTemplate TargetType="{x:Type ListBox}" > 
          <s:VirtualizingVerticalWrapPanel> 
          </s:VirtualizingVerticalWrapPanel> 
         </ControlTemplate> 
        </Setter.Value> 
       </Setter> 
      </Style> 

Теперь, в частном методе Виртуализация WrapPanel ниже Я пытаюсь получить доступ к this.ItemContainerGenerator, но я получаю нулевое значение, любая идея, в чем проблема?

private void RealizeFirstItem() 
{ 
    IItemContainerGenerator generator = this.ItemContainerGenerator; 
    GeneratorPosition pos = generator.GeneratorPositionFromIndex(0); 

    using (generator.StartAt(pos, GeneratorDirection.Forward)) 
    { 
     UIElement element = generator.GenerateNext() as UIElement; 

     generator.PrepareItemContainer(element); 

        this.AddInternalChild(element); 
    } 
} 
+0

"this.ItemContainerGenerator" означает ли это Listbox? – Ragunathan

+0

это относится к виртуализации WrapPanel, Virtualization WrapPanel используется в ControlTemplate в ListBox. – simo

ответ

7

Я думаю, что у меня была аналогичная проблема, и это помогло:

var necessaryChidrenTouch = this.Children; 
IItemContainerGenerator generator = this.ItemContainerGenerator; 

... по какой-то причине вы должны «трогать» сбор детей, чтобы для ItemContainerGenerator для инициализации.

+0

Не уверен, почему вы были заблокированы, по моему опыту вы абсолютно правы. Это ошибка, которая была отмечена еще пять лет назад членами команды avalon. – Jordan0Day

+0

Отлично, спасибо! – Andy

-1

Это потому, что вы изменили шаблон из списка, в то время как и должны иметь только что изменил ItemsPanel:

<ListBox> 
     <ListBox.ItemsPanel> 
      <ItemsPanelTemplate> 
       <s:VirtualizingVerticalWrapPanel /> 
      </ItemsPanelTemplate> 
     </ListBox.ItemsPanel> 
    </ListBox> 
0

Falck в основном правильно. На самом деле вам нужно обратиться к «InternalChildren» панели виртуализированного стека. Декомпилированы код этого свойства:

protected internal UIElementCollection InternalChildren 
    { 
     get 
     { 
      this.VerifyBoundState(); 
      if (this.IsItemsHost) 
      { 
       this.EnsureGenerator(); 
      } 
      else if (this._uiElementCollection == null) 
      { 
       this.EnsureEmptyChildren(this); 
      } 
      return this._uiElementCollection; 
     } 
    } 

«EnsureGenerator» делает работу убедившись, что генератор доступен. Очень плохой дизайн «как раз вовремя», ИМО.

2

Для приложений Windows 8.1 Metro приложение ItemContainerGenerator было лишено и вернет null. Новые Apis:

ItemsControl.ItemContainerGenerator.ItemFromContainer = ItemsControl.ItemFromContainer

ItemsControl.ItemContainerGenerator.ContainerFromItem = ItemsControl.ContainerFromItem

ItemsControl.ItemContainerGenerator.IndexFromContainer = ItemsControl.IndexFromContainer

ItemsControl.ItemContainerGenerator. ContainerFromIndex = ItemsControl.ContainerFromIndex

http://msdn.microsoft.com/en-us/library/windows/apps/dn376326.aspx

+0

благодарит alot sir – FatemehEbrahimiNik

0

Скорее всего, это проблема, связанная с виртуализацией, поэтому контейнеры ListBoxItem генерируются только для видимых в данный момент элементов (например, https://msdn.microsoft.com/en-us/library/system.windows.controls.virtualizingstackpanel(v=vs.110).aspx#Anchor_9)

Я хотел бы предложить переход на ListView вместо ListBox - он наследует от ListBox и поддерживает ScrollIntoView() метод, который вы можете использовать для управления виртуализацией;

targetListView.ScrollIntoView(itemVM); 
DoEvents(); 
ListViewItem itemContainer = targetListView.ItemContainerGenerator.ContainerFromItem(itemVM) as ListViewItem; 

(в приведенном выше примере также использует DoEvents() статический метод, описанный более подробно здесь; WPF how to wait for binding update to occur before processing more code?)

Есть несколько других незначительных различий между контрольной ListBox и ListView (What is The difference between ListBox and ListView) - которые не должны существенно влияют на ваш случай использования.

Смежные вопросы