2013-04-24 2 views
5

У меня возникла аналогичная проблема с this question, однако VirtualizingStackPanel.IsVirtualizing="False" не решила мою проблему. Кто-нибудь сталкивается с той же проблемой?ItemContainerGenerator.ContainerFromItem() возвращает null, пока VirtualizingStackPanel.IsVirtualizing = "False"

Дело в том, у меня есть пользовательская выпадающий,

<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> 

и все же я не могу получить ссылку на флажок внутри через,

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

Есть ли какие-нибудь предложения?

Что я на самом деле хочу достичь, это,

я хочу изменить Флажки IsChecked имущества, которое в зависимости от другого объекта, который может изменяться во время выполнения. Я не могу сделать это с использованием привязок из-за текущего состояния общего проекта, который я не могу изменить на этом этапе. Таким образом, в основном после того, как новый MultiSelectionComboBox создан я хочу сделать что-то вроде этого,

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); 
} 
+0

Как выглядит ваш пользовательский ComboBox? Пожалуйста, опубликуйте полный XAML ComboBox. – Clemens

+0

предложение, которое вы дали перед установкой VirtualizingStackPanel.IsVirtualizing = "False" в ItemsPanelTemplate, привело к некоторому улучшению. однако он все равно возвращает null, где мне это не нужно. –

+0

Вы уверены, что MultiSelectionComboBox фактически использует ComboBoxItem в качестве типа контейнера? И, кстати, установка «VirtualizingStackPanel.IsVirtualizing» на StackPanel также не влияет. Думаю, виртуализация здесь не проблема. – Clemens

ответ

12

попытаться выполнить UpdateLayout() перед тем this.ItemContainerGenerator.ContainerFromItem(item)

+1

Блестящий! Я потерял целый час на проблеме, пробовал разные предложения, и этот ответ помог мне! – Daniel

+2

не работает, по крайней мере, у окон телефон 8;) –

+0

Священный моль этот совет решил несколько вопросов для меня! – Puffin

2

Используйте ItemContainerGenerator.StatusChanged случае от вас ComboBox, как это:

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); 
     } 
    } 
} 
0

Поскольку моя логика была в событии SelectionChanged, я задавался вопросом, почему метод ItemContainerGenerator.ContainerFromItem всегда возвращал null, даже если Listbox.SelectedItem не был нулевым и даже более странным, Virtualisation wa выключен! Глядя на ItemContainerGenerator.Status, я увидел, что это было Primitives.GeneratorStatus.NotStarted, после чего я добавил простой тест на ItemContainerGenerator.Status == Primitives.GeneratorStatus.ContainersGenerated и, наконец, решил его таким образом и не нужно подписываться на событие Status_Changed.

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