2016-04-25 4 views
2

Я пытаюсь группировать и отображать элементы ObservableCollection, просто используя код XAML. Он хорошо работает с использованием простого CollectionViewSource и ListBox [1].Использование CollectionViewSource с TabControl

На самом деле, я бы предпочел отобразить содержимое группы в tabcontrol. Google привел меня к следующему social.msdn статья представляет которым обходной путь для отображения групп как TabControl, используя код позади:

https://social.msdn.microsoft.com/Forums/vstudio/en-US/e073f275-0826-4fca-b9da-e310ccf1713e/wpf-grouping?forum=wpf

Однако, как я использую MVVM и должны полагаться только на XAML, я не может заставить его работать. Фактически, CollectionViewSource заполняет группы (TabControl показывает правильные tabItemHeaders), но нажатие на любую из этих TabItems замерзает приложение. Вот что я пытался:

<StackPanel x:Key="ModulSelectInputParameterView"> 
    <StackPanel.Resources> 
     <CollectionViewSource x:Key="cvs" x:Name="collectionViewSource" Source="{Binding ReferencedLmtItem.ModulInputParameterCollection }"> 
      <CollectionViewSource.GroupDescriptions> 
       <PropertyGroupDescription PropertyName="Category"/> 
      </CollectionViewSource.GroupDescriptions> 
     </CollectionViewSource> 
    </StackPanel.Resources> 

    <Grid > 
     <TabControl ItemsSource="{Binding Source={StaticResource cvs}, Path=Groups, Mode=OneWay}" DataContext="{Binding Source={StaticResource cvs}, Mode=OneWay}"> 
      <!-- First Level --> 
      <TabControl.ItemTemplate> 
       <DataTemplate> 
        <TextBlock Text="{Binding Name}"/> 
       </DataTemplate> 
      </TabControl.ItemTemplate> 
      <TabControl.ContentTemplate> 
       <DataTemplate> 
        <ListBox ItemsSource="{Binding Items}"> 
         Second Level 
         <ListBox.ItemTemplate> 
          <DataTemplate> 
           <Expander Header="{Binding Name}"> 
            <ListBox ItemsSource="{Binding Items}"> 
             The Item of the Collection 
             <ListBox.ItemTemplate> 
              <DataTemplate> 
               <StackPanel Orientation="Horizontal"> 
                <TextBlock Text="{Binding Key}"/> 
                <TextBlock Text=" - "/> 
                <TextBlock Text="{Binding Value.Comment}"/> 
               </StackPanel> 
              </DataTemplate> 
             </ListBox.ItemTemplate> 
            </ListBox> 
           </Expander> 
          </DataTemplate> 
         </ListBox.ItemTemplate> 
        </ListBox> 
       </DataTemplate> 
      </TabControl.ContentTemplate> 
     </TabControl> 
    </Grid> 

</StackPanel> 

[1]: Этот мир XAML работает, как ожидалось, но использует WrapPanel для отображения групп содержимого:

<StackPanel x:Key="ModulSelectInputParameterView"> 
    <StackPanel.Resources> 
     <CollectionViewSource x:Key="cvs" x:Name="collectionViewSource" Source="{Binding ReferencedLmtItem.ModulInputParameterCollection }"> 
      <CollectionViewSource.GroupDescriptions> 
       <PropertyGroupDescription PropertyName="Category"/> 
      </CollectionViewSource.GroupDescriptions> 
     </CollectionViewSource> 
    </StackPanel.Resources> 

    <ListBox ItemsSource="{Binding Source={StaticResource cvs}}" VerticalContentAlignment="Top" ItemContainerStyle="{StaticResource ModulSelectInputParameterListBoxItemContainerStyle}" ScrollViewer.HorizontalScrollBarVisibility="Disabled"> 
     <ListBox.GroupStyle> 
      <GroupStyle> 
       <GroupStyle.HeaderTemplate> 
        <DataTemplate> 
         <Border BorderBrush="DarkGray" BorderThickness="2" Margin="2"> 
          <TextBlock FontWeight="Bold" FontSize="14" Text="{Binding Path=Name}" HorizontalAlignment="Center" MinWidth="100"/> 
         </Border> 
        </DataTemplate> 
       </GroupStyle.HeaderTemplate> 
       <GroupStyle.Panel> 
        <ItemsPanelTemplate> 
         <WrapPanel Orientation="Horizontal" Margin="2"/> 
        </ItemsPanelTemplate> 
       </GroupStyle.Panel> 
       <GroupStyle.ContainerStyle> 
        <Style TargetType="{x:Type GroupItem}" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"> 
         <Setter Property="Control.Template"> 
          <Setter.Value> 
           <ControlTemplate TargetType="{x:Type GroupItem}"> 
            <Border BorderThickness="2" BorderBrush="DarkGray"> 
             <StackPanel> 
              <ContentPresenter Content="{TemplateBinding ContentControl.Content}" ContentTemplate="{TemplateBinding ContentControl.ContentTemplate}" ContentStringFormat="{TemplateBinding ContentControl.ContentStringFormat}" /> 
              <ItemsPresenter Margin="2,0,2,2" /> 
             </StackPanel> 
            </Border> 
           </ControlTemplate> 
          </Setter.Value> 
         </Setter> 
        </Style> 
       </GroupStyle.ContainerStyle> 
      </GroupStyle> 

     </ListBox.GroupStyle> 
     <ListBox.ItemsPanel> 
      <ItemsPanelTemplate> 
       <WrapPanel IsItemsHost="True" Orientation="Vertical" VerticalAlignment="Top"/> 
      </ItemsPanelTemplate> 
     </ListBox.ItemsPanel> 

    </ListBox> 
</StackPanel> 

ответ

1

Я думаю, что есть что-то не так с вашим обязательный код должен работать. Чтобы получить одни и те же элементы в обоих ListBoxes пытаются связать второй ListBox ItemsSource к первому ListBox ItemsSource, как это:

<ListBox ItemsSource="{Binding Items}" Name="ListBox"> 

            <ListBox.ItemTemplate> 
             <DataTemplate> 
              <Expander Header="{Binding Key}"> 
               <ListBox ItemsSource="{Binding ItemsSource, ElementName=ListBox}"> 

                <ListBox.ItemTemplate> 
                 <DataTemplate> 
                  <StackPanel Orientation="Horizontal"> 
                   <TextBlock Text="{Binding Key}"/> 
                   <TextBlock Text=" - "/> 
                   <TextBlock Text="{Binding Value}"/> 
                  </StackPanel> 
                 </DataTemplate> 
                </ListBox.ItemTemplate> 
               </ListBox> 
              </Expander> 
             </DataTemplate> 
            </ListBox.ItemTemplate> 
           </ListBox> 
+0

К сожалению, это не решит проблему. Но я получаю следующее сообщение об ошибке, возможно, причина этой ошибки может помочь решить эту проблему: «Потенциальный цикл в дереве, найденный при построении маршрута событий». – Bechi

+0

Думаете, вы должны удалить «datacontext» из своего TabControl – Johannes

+1

Действительно, сообщение об ошибке дало подсказку: Это не был (ненужный) DataContext. Это проблема с DataTemplates в стилях, которые обновляются с использованием datatriggers, которые вызывают вышеупомянутый цикл в дереве. Joh.Решение похоже работает нормально, и я дам краткое сообщение об ошибке в отдельном ответе. – Bechi

2

Благодаря Joh, которые помогли с соответствующим DataBinding. Однако причина была совершенно иной: быстрое и грязное решение дано ниже [1]:

В принципе, мне не хватало, что вышеупомянутый элемент управления вкладками вложен в внешний элемент управления Tab в моем главном окне. Я не уверен, что следующее описание является полностью правильным [1], но, на мой взгляд, причина в следующем:

  • Внешний TabControl использует стиль для отображения его содержимого. Этот контент относится к ViewModel, который содержит вышеупомянутую наблюдаемую коллекцию, которая, в свою очередь, должна быть ItemsSource CollectionViewSource, который передает внутреннюю tabControl с группами.
  • Как я определил этот стиль только во внешних вкладках TabControl.Resources и пропустил определение отдельного стиля для внутренней вкладки Control, внутренний tabcontrol наследует внешний стиль и пытается отобразить его данные с использованием одного и того же контента.
  • Этот контент снова является еще одним внутренним tabControl, который вызывает другой внутренний tabControl и так далее.

[1] Определение пустой стиль в inenr tabControl.Resources решить эту проблему:

<TabControl.Resources> 
       <Style TargetType="TabItem"> 

       </Style> 
      </TabControl.Resources> 

Я был бы счастлив, если кто-то может подтвердить эту идею или предоставить некоторые ссылки на хорошо известные проблемы с общим стилей в вложенных элементах управления.

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