2013-04-24 12 views
5

Sto affrontando un problema simile con this question tuttavia VirtualizingStackPanel.IsVirtualizing="False" non ha risolto il mio problema. C'è qualcuno che sta affrontando lo stesso problema?ItemContainerGenerator.ContainerFromItem() restituisce null mentre VirtualizingStackPanel.IsVirtualizing = "False"

La cosa è che ho un combobox personalizzato,

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

, eppure non riesco a ottenere un riferimento alla casella di controllo interno via,

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

È stato rilevato qualche suggerimento?

Quello che in realtà voglio ottenere è,

voglio cambiare caselle proprietà IsChecked che dipende su un altro oggetto che può cambiare in fase di esecuzione. Non posso farlo con l'uso dei binding a causa dello stato attuale del progetto complessivo che non posso cambiare a questo punto. Quindi, in pratica una volta che la nuova MultiSelectionComboBox è creato voglio fare qualcosa di simile,

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

Che aspetto ha il tuo ComboBox personalizzato? Per favore pubblica l'intero XAML del ComboBox. – Clemens

+0

il suggerimento che hai dato prima di impostare VirtualizingStackPanel.IsVirtualizing = "False" a ItemsPanelTemplate ha comportato qualche miglioramento. tuttavia restituisce ancora null dove ho bisogno di non farlo. –

+0

Sei sicuro che MultiSelectionComboBox usi effettivamente ComboBoxItem come tipo di contenitore? Inoltre, l'impostazione di 'VirtualizingStackPanel.IsVirtualizing' su uno StackPanel non ha alcun effetto. Immagino che la virtualizzazione non sia il problema qui. – Clemens

risposta

12

provare eseguire UpdateLayout() prima this.ItemContainerGenerator.ContainerFromItem(item) evento

+1

Brillante! Ho perso un'ora intera sul problema provando diversi suggerimenti e questa risposta mi ha aiutato! – Daniel

+2

non funziona, almeno al windows phone 8;) –

+0

Holy Moly questo consiglio ha risolto diversi problemi per me! – Puffin

2

Usa ItemContainerGenerator.StatusChanged da voi casella combinata in questo modo:

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

Poiché la mia logica era nell'evento SelectionChanged, mi sono chiesto perché il metodo ItemContainerGenerator.ContainerFromItem restituiva sempre null anche se lo Listbox.SelectedItem non era nullo e ancora più strano, Virtualizzazione wa s spento! Guardando il ItemContainerGenerator.Status ho visto che era Primitives.GeneratorStatus.NotStarted quindi ho aggiunto un semplice test su ItemContainerGenerator.Status == Primitives.GeneratorStatus.ContainersGenerated e alla fine l'ho risolto in questo modo e non c'è bisogno di iscrivermi all'evento Status_Changed.

Problemi correlati