Why does ItemContainerGenerator return null?

前端 未结 5 1989
闹比i
闹比i 2020-12-21 23:53

I have a ListBox, and I need to set its ControlTemplate to a Virtualizing WrapPanel which is a class that extends VirtualizingPanel, using a style that looks like this:

相关标签:
5条回答
  • 2020-12-22 00:41

    Falck is mostly correct. Actually, you need to reference the 'InternalChildren' of the virtualized stack panel. The decompiled code for this property is:

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

    The 'EnsureGenerator' does the work of making sure that a generator is available. Very poor 'just in time' design, IMO.

    0 讨论(0)
  • 2020-12-22 00:45

    For Windows 8.1 Metro apps, the ItemContainerGenerator was depricated and will return null. New 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 讨论(0)
  • 2020-12-22 00:49

    I think I had a similar problem and this helped:

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

    ... for some reason you have to "touch" the children collection in order for the ItemContainerGenerator to initialize properly.

    0 讨论(0)
  • 2020-12-22 00:51

    Most probably this is a virtualization-related issue so ListBoxItem containers get generated only for currently visible items (e.g. https://msdn.microsoft.com/en-us/library/system.windows.controls.virtualizingstackpanel(v=vs.110).aspx#Anchor_9)

    I'd suggest switching to ListView instead of ListBox - it inherits from ListBoxand it supports ScrollIntoView() method which you can utilize to control virtualization;

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

    (the example above also utilizes the DoEvents() static method explained in more detail here; WPF how to wait for binding update to occur before processing more code?)

    There are a few other minor differences between the ListBox and ListView controls (What is The difference between ListBox and ListView) - which should not essentially affect your use case.

    0 讨论(0)
  • 2020-12-22 00:54

    This is because you changed the Template of the Listbox, while u should have just changed the ItemsPanel:

        <ListBox>
            <ListBox.ItemsPanel>
                <ItemsPanelTemplate>
                    <s:VirtualizingVerticalWrapPanel />
                </ItemsPanelTemplate>
            </ListBox.ItemsPanel>
        </ListBox>
    
    0 讨论(0)
提交回复
热议问题