2013-04-24 10 views
5

Ich bin mit einem ähnlichen Problem konfrontiert mit this question aber VirtualizingStackPanel.IsVirtualizing="False" löste mein Problem nicht. Gibt es jemanden, der das gleiche Problem hat?ItemContainerGenerator.ContainerFromItem() gibt null zurück, während VirtualizingStackPanel.IsVirtualizing = "False"

Die Sache ist, ich habe eine benutzerdefinierte 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> 

und doch kann ich nicht einen Verweis auf die Checkbox innen über,

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

Gibt es irgendwelche Vorschläge bekommen?

Was ich will, tatsächlich zu erreichen ist,

ich will Kontrollkästchen IsChecked Eigenschaft ändern, die auf einem anderen Objekt abhängig, die auf der Laufzeit ändern können. Das kann ich aufgrund des aktuellen Zustands des Gesamtprojekts nicht mit Bindings tun, was ich an dieser Stelle nicht ändern kann. Also im Grunde, sobald die neue MultiSelectionComboBox geschaffen, die ich so etwas wie dies tun will,

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

Wie sieht Ihre benutzerdefinierte ComboBox aus? Bitte posten Sie den vollen XAML der ComboBox. – Clemens

+0

Der Vorschlag, den Sie vor der Einstellung von VirtualizingStackPanel.IsVirtualizing = "False" auf ItemsPanelTemplate gaben, führte zu einer gewissen Verbesserung. aber es gibt immer noch null, wo ich es nicht brauche. –

+0

Sind Sie sicher, dass MultiSelectionComboBox tatsächlich ComboBoxItem als Containertyp verwendet? Und übrigens hat das Setzen von 'VirtualizingStackPanel.IsVirtualizing' auf einem StackPanel auch keine Auswirkungen. Ich denke, Virtualisierung ist hier nicht das Problem. – Clemens

Antwort

12

versuchen ausführen UpdateLayout() vor this.ItemContainerGenerator.ContainerFromItem(item)

+1

Brilliant! Ich habe eine ganze Stunde auf das Problem mit verschiedenen Vorschlägen verloren und diese Antwort hat mir geholfen! – Daniel

+2

funktioniert nicht, zumindest bei Windows Phone 8;) –

+0

Holy Moly dieser Tipp löste mehrere Probleme für mich! – Puffin

2

Verwenden ItemContainerGenerator.StatusChanged Ereignis von Ihnen wie folgt 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

Als meine Logik im SelectionChanged-Ereignis war, fragte ich mich, warum die ItemContainerGenerator.ContainerFromItem-Methode immer null zurückgab, auch wenn Listbox.SelectedItem nicht null und noch seltsamer war, Virtualisierung wa s ausgeschaltet! Mit Blick auf die ItemContainerGenerator.Status sah ich, dass es Primitives.GeneratorStatus.NotStarted war, dann fügte ich einen einfachen Test auf ItemContainerGenerator.Status == Primitives.GeneratorStatus.ContainersGenerated und löste es schließlich auf diese Weise und keine Notwendigkeit, das Status_Changed-Ereignis teilnehmen.

Verwandte Themen