2013-04-24 18 views
5

Tôi đang đối mặt với một vấn đề tương tự với this question tuy nhiên VirtualizingStackPanel.IsVirtualizing="False" không giải quyết được vấn đề của tôi. Có ai phải đối mặt với cùng một vấn đề không?ItemContainerGenerator.ContainerFromItem() trả về null trong khi VirtualizingStackPanel.IsVirtualizing = "False"

Vấn đề là tôi có một combobox tùy chỉnh,

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

nhưng tôi không thể có được một tham chiếu đến các hộp kiểm bên qua,

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

Có bất cứ đề nghị?

gì tôi thực sự muốn đạt được là,

tôi muốn thay đổi hộp kiểm tài sản ischecked đó là tùy thuộc vào một đối tượng khác mà có thể thay đổi về thời gian chạy. Tôi không thể làm điều đó với việc sử dụng các ràng buộc do trạng thái hiện tại của dự án tổng thể mà tôi không thể thay đổi vào thời điểm này. Vì vậy, về cơ bản khi MultiSelectionComboBox mới được tạo ra tôi muốn làm một cái gì đó như thế này,

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 tùy chỉnh của bạn trông như thế nào? Vui lòng đăng XAML đầy đủ của ComboBox. – Clemens

+0

đề xuất bạn đã cung cấp trước khi đặt VirtualizingStackPanel.IsVirtualizing = "False" thành ItemsPanelTemplate dẫn đến một số cải tiến. tuy nhiên nó vẫn trả về null khi tôi không cần. –

+0

Bạn có chắc chắn rằng MultiSelectionComboBox thực sự sử dụng ComboBoxItem như là loại container? Và bằng cách này, thiết lập 'VirtualizingStackPanel.IsVirtualizing' trên StackPanel cũng không có hiệu lực. Tôi đoán ảo hóa không phải là vấn đề ở đây. – Clemens

Trả lời

12

thử thực hiện UpdateLayout() trước this.ItemContainerGenerator.ContainerFromItem(item) kiện

+1

Brilliant! Tôi đã mất cả một giờ để giải quyết các đề xuất khác nhau và câu trả lời này đã giúp tôi! – Daniel

+2

không hoạt động, ít nhất là tại cửa sổ điện thoại 8;) –

+0

Mẹo moly này đã giải quyết được một số vấn đề đối với tôi! – Puffin

2

Sử dụng ItemContainerGenerator.StatusChanged từ bạn combobox như thế này:

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

Khi logic của tôi nằm trong sự kiện SelectionChanged, tôi tự hỏi tại sao phương thức ItemContainerGenerator.ContainerFromItem luôn trả về null ngay cả khi Listbox.SelectedItem không phải là null và thậm chí còn kỳ lạ hơn, Virtualisation wa s đã tắt! Nhìn vào ItemContainerGenerator.Status tôi thấy rằng nó là Primitives.GeneratorStatus.NotStarted sau đó tôi đã thêm một thử nghiệm đơn giản trên ItemContainerGenerator.Status == Primitives.GeneratorStatus.ContainersGenerated và cuối cùng đã giải quyết nó theo cách đó và không cần phải subsribe cho sự kiện Status_Changed.