2013-04-24 10 views
5

Mam do czynienia z podobnym problemem z this question jednak VirtualizingStackPanel.IsVirtualizing="False" nie rozwiązał mojego problemu. Czy jest ktoś, kto ma ten sam problem?ItemContainerGenerator.ContainerFromItem() zwraca null podczas VirtualizingStackPanel.IsVirtualizing = "False"

Chodzi o to mam zwyczaj 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> 

i jeszcze nie mogę się odniesienie do wyboru wewnątrz poprzez,

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

Czy istnieją jakieś sugestie?

co faktycznie chcemy osiągnąć to,

chcę zmienić wyboru IsChecked nieruchomości, które w zależności od innego obiektu, który można zmienić na starcie. Nie mogę tego zrobić przy użyciu powiązań ze względu na obecny stan całego projektu, którego nie mogę zmienić w tym momencie. Więc w zasadzie po utworzeniu nowego MultiSelectionComboBox chcę zrobić coś takiego,

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

Jak wygląda Twój niestandardowy wygląd ComboBox? Opublikuj pełny XAML w ComboBox. – Clemens

+0

sugestia, którą podałeś przed ustawieniem VirtualizingStackPanel.IsVirtualizing = "False" na ItemsPanelTemplate spowodowała pewne ulepszenie. jednak nadal zwraca wartość null tam, gdzie tego potrzebuję. –

+0

Czy jesteś pewien, że MultiSelectionComboBox faktycznie używa ComboBoxItem jako typ kontenera? A przy okazji, ustawienie 'VirtualizingStackPanel.IsVirtualizing' na StackPanel również nie ma żadnego efektu. Myślę, że wirtualizacja nie jest tutaj problemem. – Clemens

Odpowiedz

12

spróbować wykonać UpdateLayout() przed this.ItemContainerGenerator.ContainerFromItem(item) imprezy

+1

Genialny! Straciłem całą godzinę na problem próbując różnych sugestii i ta odpowiedź pomogła mi! – Daniel

+2

nie działa, przynajmniej na Windows Phone 8;) –

+0

Święty Moly ten napiwek rozwiązał kilka problemów dla mnie! – Puffin

2

Zastosowanie ItemContainerGenerator.StatusChanged od ciebie ComboBox tak:

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

Ponieważ moja logika była w zdarzeniu SelectionChanged, zastanawiałem się, dlaczego metoda ItemContainerGenerator.ContainerFromItem zawsze zwracała wartość null, nawet jeśli Listbox.SelectedItem nie było zerowe, a jeszcze dziwniejsze, wiryzacja s wyłączone! Patrząc na ItemContainerGenerator.Status zobaczyłem, że był to Primitives.GeneratorStatus.NotStarted, a następnie dodałem prosty test na ItemContainerGenerator.Status == Primitives.GeneratorStatus.ContainersGenerated i ostatecznie rozwiązałem go w ten sposób i nie ma potrzeby subskrypcji do zdarzenia Status_Changed.