2010-07-20 155 views
1

我有一個列表框,我需要它的控件模板設置爲虛擬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 2010-07-20 12:02:16

+0

這是指Virtualizing WrapPanel,虛擬化WrapPanel用在ListBox的ControlTemplate中 – simo 2010-07-22 06:52:37

回答

7

我想我也有類似的問題,這有助於:

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

...由於某種原因,你必須以「觸摸」孩子們收集了ItemContainerGenerator正確初始化。

+0

不知道你爲什麼被低估,按照我的經驗你是絕對正確的。這是一個早在5年前由Avalon團隊成員注意到的錯誤。 – Jordan0Day 2011-06-08 16:09:51

+0

完美,謝謝! – Andy 2013-03-04 11:47:53

-1

這是因爲你改變了ListBox的模板,而ü應該有隻是改變了ItemsPanel:

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

法爾克大多是正確的。實際上,你需要引用虛擬化堆棧面板的'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'確保生成器可用。國際海事組織(IMO)非常糟糕的「及時」設計。

2

對於Windows 8.1 Metro應用程序,ItemContainerGenerator被取消並返回null。新的API:

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

非常感謝先生 – FatemehEbrahimiNik 2016-05-21 07:36:14

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?

還有其他一些次要的ListBoxListView對照之間(What is The difference between ListBox and ListView)差異 - 這不應該基本上影響你的用例。