ItemContainerGenerator.ContainerFromItem() returns null while VirtualizingStackPanel.IsVirtualizing=“False”

生来就可爱ヽ(ⅴ<●) 提交于 2019-12-01 04:43:54

问题


I'm facing a similar problem with this question however VirtualizingStackPanel.IsVirtualizing="False" didn't solve my problem. Is there anyone facing the same issue?

The thing is I have a custom combobox,

<Style TargetType="{x:Type MultiSelectionComboBox}"  >
    <Setter Property="VerticalContentAlignment" Value="Center"/>
    <Setter Property="ItemsPanel">
        <Setter.Value>
            <ItemsPanelTemplate>
                <StackPanel Orientation="Vertical"
                VerticalAlignment="Center"
                HorizontalAlignment="Center"
                VirtualizingStackPanel.IsVirtualizing="False"/>
            </ItemsPanelTemplate>
        </Setter.Value>
    </Setter>
    <Setter Property="ItemTemplate">
        <Setter.Value>
            <DataTemplate>
                <StackPanel Orientation="Horizontal" x:Name="ItemStack" VirtualizingStackPanel.IsVirtualizing="False">
                    <CheckBox x:Name="CheckBoxItem"
                        Command="{Binding SelectItem, RelativeSource={RelativeSource AncestorType={x:Type MultiSelectionComboBox}}}"
                        CommandParameter="{Binding Key}"
                              >
                    </CheckBox>
                    <TextBlock Text="{Binding DisplayText}"></TextBlock>
                </StackPanel>
            </DataTemplate>
        </Setter.Value>
    </Setter>
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type ComboBox}">
                <Grid x:Name="Placement" SnapsToDevicePixels="true">
                    <Grid.ColumnDefinitions>
                        <ColumnDefinition Width="*"/>
                        <ColumnDefinition Width="Auto"/>
                    </Grid.ColumnDefinitions>
                    <Border BorderThickness="1" BorderBrush="Black">
                        <TextBox IsReadOnly="True" Grid.Column="0" 
                                 Text="{Binding Text, UpdateSourceTrigger=PropertyChanged, RelativeSource={RelativeSource AncestorType={x:Type MultiSelectionComboBox}}}">
                        </TextBox>
                    </Border>
                    <Popup x:Name="PART_Popup" 
                               Grid.Column="0"
                               Focusable="False"
                               Grid.ColumnSpan="2"
                               IsOpen="{Binding IsDropDownOpen, RelativeSource={RelativeSource TemplatedParent}, Mode=TwoWay}"
                               Placement="Bottom"
                               VerticalOffset="-1"
                               PlacementTarget="{Binding ElementName=LayoutRoot}">
                        <Popup.Resources>
                            <Style TargetType="{x:Type ScrollBar}" BasedOn="{StaticResource {x:Type ScrollBar}}">
                                <Style.Triggers>
                                    <Trigger Property="Orientation" Value="Vertical">
                                        <Setter Property="BorderThickness" Value="0"/>
                                    </Trigger>
                                </Style.Triggers>
                            </Style>
                        </Popup.Resources>
                        <ScrollViewer x:Name="DropDownScrollViewer"
                                          Background="{StaticResource Background}"
                                          BorderBrush="{TemplateBinding BorderBrush}"
                                          BorderThickness="{TemplateBinding BorderThickness}"
                                          MinWidth="{Binding ActualWidth, ElementName=LayoutRoot}"
                                          MaxHeight="{TemplateBinding MaxDropDownHeight}">
                            <ItemsPresenter KeyboardNavigation.DirectionalNavigation="Contained"/>
                        </ScrollViewer>
                    </Popup>
                    <ToggleButton IsEnabled="{Binding IsEnabled, UpdateSourceTrigger=PropertyChanged, RelativeSource={RelativeSource AncestorType={x:Type MultiSelectionComboBox}}}" Grid.Column="1" IsChecked="{Binding IsDropDownOpen, Mode=TwoWay, RelativeSource={RelativeSource TemplatedParent}}" Style="{StaticResource ComboBoxToggleButton}"/>
                </Grid>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>
</ResourceDictionary>

and yet I can't get a reference to the checkbox inside via,

this.ItemContainerGenerator.ContainerFromItem(this.Items[0]) as ComboBoxItem;

Is there any suggestions?

What i actually want to achieve is,

i want to change checkboxes ischecked property which is depending on an other object which can change on runtime. I can't do it with using bindings due to the current state of the overall project which i can not change at this point. So basically once the new MultiSelectionComboBox is created i want to do something like this,

foreach (object item in this.Items)
{
    ComboBoxItem comboBoxItem = this.ItemContainerGenerator.ContainerFromItem(item) as ComboBoxItem;
    if (comboBoxItem == null)
        continue;
    FrameworkElement element = comboBoxItem.ContentTemplate.LoadContent() as FrameworkElement;
    CheckBox checkBox = element.FindName("CheckBoxItem") as CheckBox;
    checkBox.IsChecked = this.SelectedItem.Contains(item);
}

回答1:


try execute UpdateLayout() before this.ItemContainerGenerator.ContainerFromItem(item)




回答2:


Use ItemContainerGenerator.StatusChanged event from you ComboBox like this:

myComboBox.ItemContainerGenerator.StatusChanged += ItemContainerGenerator_StatusChanged;

void ItemContainerGenerator_StatusChanged(object sender, System.EventArgs e)
{
    if (myComboBox.ItemContainerGenerator.Status == GeneratorStatus.ContainersGenerated)
    {
        foreach (var item in myComboBox.Items)
        {
            var container = (ComboBoxItem)LanguageComboBox.ItemContainerGenerator.ContainerFromItem(item);
        }
    }
}



回答3:


As my logic was in the SelectionChanged event, i wondered why the ItemContainerGenerator.ContainerFromItem method always returned null even if the Listbox.SelectedItem was not null and even more strange, Virtualisation was turned off! Looking at the ItemContainerGenerator.Status i saw that it was Primitives.GeneratorStatus.NotStarted then i added a simple test on ItemContainerGenerator.Status == Primitives.GeneratorStatus.ContainersGenerated and finally solved it that way and no need to subsribe to the Status_Changed event.



来源:https://stackoverflow.com/questions/16184172/itemcontainergenerator-containerfromitem-returns-null-while-virtualizingstackp

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!