Поле со списком из нескольких элементов с заголовками?

Возможно ли иметь "заголовки столбцов" в поле со списком, привязанными к нескольким элементам? Например, поле со списком, которое отображает имя человека. Поле со списком будет отображать Джона Доу. Но я хотел бы отобразить заголовки столбцов:

First   Last
John    Doe
Jane    Doe
Jimmy   Doe

Возможно ли это без использования сетки данных? Как насчет простого решения, которое включает использование сетки данных? Я нашел одно решение для встраивания сетки данных в поле со списком, но это выглядит сложно и требует MS Blend.

Я был бы счастлив, если бы я мог просто получить несколько заголовков в качестве первого ряда в раскрывающемся списке.

г

Вот мой код xaml с попыткой HB, которая приводит к ошибке компиляции, как упомянуто в комментариях.

xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:dg="http://schemas.microsoft.com/wpf/2008/toolkit"
<ComboBox Name="cboPlaceNames" Grid.IsSharedSizeScope="True" ItemsSource="{DynamicResource items}" Height="22" Width="285" Margin="0,6,165,0" SelectedIndex="0" HorizontalAlignment="Right" VerticalAlignment="Top" SelectionChanged="cboPlaceNames_SelectionChanged">
  <ComboBox.Resources>
    <CompositeCollection x:Key="items">
      <ComboBoxItem IsEnabled="False">
        <Grid TextElement.FontWeight="Bold">
          <Grid.ColumnDefinitions>
            <ColumnDefinition SharedSizeGroup="A"/>
            <ColumnDefinition Width="5"/>
            <ColumnDefinition SharedSizeGroup="B"/>
            <ColumnDefinition Width="5"/>
            <ColumnDefinition SharedSizeGroup="C"/>
          </Grid.ColumnDefinitions>
          <Grid.Children>
            <TextBlock Grid.Column="0" Text="Name"/>
            <TextBlock Grid.Column="2" Text="CLLI"/>
            <TextBlock Grid.Column="4" Text="Street"/>
          </Grid.Children>
        </Grid>
      </ComboBoxItem>
      <Separator/>
      <CollectionContainer Collection="{Binding Source={x:Reference cboPlaceNames}, Path=DataContext.Data}"/>
    </CompositeCollection>

    <DataTemplate DataType="x:Type obj:PlaceName">
      <Grid>
        <Grid.ColumnDefinitions>
          <ColumnDefinition SharedSizeGroup="A"/>
          <ColumnDefinition Width="5"/>
          <ColumnDefinition SharedSizeGroup="B"/>
          <ColumnDefinition Width="5"/>
          <ColumnDefinition SharedSizeGroup="C"/>
        </Grid.ColumnDefinitions>
        <Grid.Children>
          <TextBlock Grid.Column="0" Text="{Binding Name}"/>
          <TextBlock Grid.Column="2" Text="{Binding CLLI}"/>
          <TextBlock Grid.Column="4" Text="{Binding Street}"/>
        </Grid.Children>
      </Grid>
    </DataTemplate>
  </ComboBox.Resources>
</ComboBox>      

4 ответа

Решение

Пример:

<ComboBox Name="cb" Grid.IsSharedSizeScope="True" ItemsSource="{DynamicResource items}">
    <ComboBox.Resources>
        <CompositeCollection x:Key="items">
            <ComboBoxItem IsEnabled="False">
                <Grid TextElement.FontWeight="Bold">
                    <Grid.ColumnDefinitions>
                        <ColumnDefinition SharedSizeGroup="A"/>
                        <ColumnDefinition Width="5"/>
                        <ColumnDefinition SharedSizeGroup="B"/>
                    </Grid.ColumnDefinitions>
                    <Grid.Children>
                        <TextBlock Grid.Column="0" Text="Name"/>
                        <TextBlock Grid.Column="2" Text="Occupation"/>
                    </Grid.Children>
                </Grid>
            </ComboBoxItem>
            <Separator/>
            <CollectionContainer Collection="{Binding Source={x:Reference cb}, Path=DataContext.Data}"/>
        </CompositeCollection>

        <DataTemplate DataType="{x:Type obj:Employee}">
            <Grid>
                <Grid.ColumnDefinitions>
                    <ColumnDefinition SharedSizeGroup="A"/>
                    <ColumnDefinition Width="5"/>
                    <ColumnDefinition SharedSizeGroup="B"/>
                </Grid.ColumnDefinitions>
                <Grid.Children>
                    <TextBlock Grid.Column="0" Text="{Binding Name}"/>
                    <TextBlock Grid.Column="2" Text="{Binding Occupation}"/>
                </Grid.Children>
            </Grid>
        </DataTemplate>
    </ComboBox.Resources>
</ComboBox>

Обратите внимание, что получение Collectionобязательное право не так просто, потому что нет DataContext ни VisualTree, чтобы положиться, ElementName а также RelativeSource не работает, это потому что CompositeCollection это просто коллекция, а не FrameworkElement.

Помимо этого, способ сделать это - через сетки, которые имеют столбцы общего размера. DataTemplate применяется автоматически через DataType,

Скриншот

Изменить: Установка заголовка-ComboBoxItem's IsHitTestVisible собственность на False недостаточно, так как он все еще может быть выбран с помощью клавиатуры. Я теперь изменил это на IsEnabled="False" что немного затухает предмет. Вы могли бы, вероятно, изменить шаблон этого элемента, чтобы не делать этого. Или, если вы найдете другой способ отключить его от выбора, который, конечно, тоже сработает.

Самый простой способ добавить заголовки столбцов в комбинированный список - это использовать список в комбинированном списке. Следующий код дает решение для этого.

            <ComboBox HorizontalAlignment="Center" 
                      IsTextSearchEnabled="False" Width="200"                                            
                      IsEditable="True" Text="{Binding }"> 
                 <ListView ItemsSource="{Binding YOURITEMSOURCE}" 
                        SelectedItem="{Binding Path=SELECTEDITEMSOURCE}"
                         Height="200" ScrollViewer.VerticalScrollBarVisibility="Visible">                  
                           <ListView.View>
                               <GridView>
                                  <GridViewColumn Width="130"  Header="Name" DisplayMemberBinding="{Binding Name}"   />
                                  <GridViewColumn Width="130" Header="Occupation" DisplayMemberBinding="{Binding Occupation}" />
                                  <GridViewColumn Width="130"  Header="Age" DisplayMemberBinding="{Binding Age}" />
                                  <GridViewColumn Width="130" Header="Salary" DisplayMemberBinding="{Binding Salary}" />
                               </GridView>
                           </ListView.View>
                  </ListView>

            </ComboBox>

Мне понравился ответ Нанды, потому что это было то, чего я пытался достичь. Однако текстовое поле поля со списком не будет работать правильно.

Поскольку мне лень, чтобы обойти это, я создал StackPanel с горизонтальной ориентацией, с TextBox, привязанным к полю из выбранного элемента, и Combo Box со встроенным ListView. Поле со списком теперь имеет ширину 20, поэтому отображается только стрелка вниз (вы можете поиграть с шириной и полями, чтобы получить правильный вид. Это делает текстовое поле похожим на поле со списком со всеми преимуществами ListView, и намного меньше кодирования.

Надеюсь, это поможет.введите описание изображения здесь

Мне нравится ответ HB, но, к сожалению, когда я его использую, я вижу ошибки привязки данных в выходных данных для заголовка ComboBoxItem"s HorizontalContentAlignment а также VerticalContentAlignment свойства:

Не удается найти источник для привязки со ссылкой 'RelativeSource FindAncestor, AncestorType='System.Windows.Controls.ItemsControl', AncestorLevel='1''. BindingExpression:Path=HorizontalContentAlignment; DataItem= NULL; целевым элементом является 'ComboBoxItem' (Name=''); Свойство target - "HorizontalContentAlignment" (тип "HorizontalAlignment")

Они не вызывают сбой программы, но они загромождают вывод и вызывают ощутимые задержки при запуске отладочных сборок. Все, что их вызывает, кажется, глубоко в недрах ComboBox или же ComboBoxItem; в любом случае, я не мог придумать, как их предотвратить (установить эти свойства вручную или с помощью Style не помогло). Так что я закончил с небольшим изменением. Это длиннее и хакернее, чем мне бы хотелось, но оно выполняет свою работу:

<ComboBox Name="cb" Grid.IsSharedSizeScope="True" ItemsSource="{DynamicResource items}">
 <ComboBox.Resources>
    <!-- We'll use this dummy value to represent the header row. -->
    <!-- The type and value are arbitrary; we just need a unique type -->
    <!-- for DataTemplate selection to work with. -->
    <system:Int32 x:Key="HeaderPlaceholder">-1</system:Int32>

    <CompositeCollection x:Key="items">
      <StaticResource ResourceKey="HeaderPlaceholder" />
      <CollectionContainer Collection="{Binding Source={x:Reference cb},
         Path=DataContext.Data}"/>
    </CompositeCollection>

    <!-- DataTemplate for the header item -->
    <DataTemplate DataType="{x:Type system:Int32}">
      <DataTemplate.Resources>
        <!-- Make the TextBlocks black even though they are disabled -->
        <Style TargetType="TextBlock">
          <Style.Triggers>
            <Trigger Property="IsEnabled" Value="False">
              <Setter Property="Foreground" Value="Black" />
            </Trigger>
          </Style.Triggers>
        </Style>
      </DataTemplate.Resources>

      <StackPanel>
        <Grid TextElement.FontWeight="Bold">
          <Grid.ColumnDefinitions>
            <ColumnDefinition SharedSizeGroup="A"/>
            <ColumnDefinition Width="5"/>
            <ColumnDefinition SharedSizeGroup="B"/>
          </Grid.ColumnDefinitions>
          <Grid.Children>
              <TextBlock Grid.Column="0" Text="Name"/>
              <TextBlock Grid.Column="2" Text="Occupation"/>
          </Grid.Children>
        </Grid>
        <Separator />
      </StackPanel>
    </DataTemplate>

    <!-- DataTemplate for a normal, selectable item -->
    <DataTemplate DataType="{x:Type obj:Employee}">
      <Grid>
        <Grid.ColumnDefinitions>
          <ColumnDefinition SharedSizeGroup="A"/>
          <ColumnDefinition Width="5"/>
          <ColumnDefinition SharedSizeGroup="B"/>
        </Grid.ColumnDefinitions>
        <Grid.Children>
          <TextBlock Grid.Column="0" Text="{Binding Name}"/>
          <TextBlock Grid.Column="2" Text="{Binding Occupation}"/>
        </Grid.Children>
      </Grid>
    </DataTemplate>
  </ComboBox.Resources>

  <ComboBox.ItemContainerStyle>
    <!-- Make sure the header item is disabled so it can't be selected -->
    <Style TargetType="ComboBoxItem">
      <Style.Triggers>
        <Trigger Property="DataContext" Value="{StaticResource HeaderPlaceholder}">
          <Setter Property="IsEnabled" Value="False" />
        </Trigger>
      </Style.Triggers>
    </Style>
  </ComboBox.ItemContainerStyle>
</ComboBox>

Примените следующий стиль к ComboBox.

<Style x:Key="ListViewComboBox" TargetType="{x:Type ComboBox}">
    <Style.Resources>
        <SolidColorBrush x:Key="{x:Static SystemColors.HighlightBrushKey}" 
                         Color="LightBlue"/>
    </Style.Resources>
    <Setter Property="ScrollViewer.CanContentScroll" Value="true"/>
    <Setter Property="ScrollViewer.HorizontalScrollBarVisibility" Value="Auto"/>
    <Setter Property="ScrollViewer.VerticalScrollBarVisibility" Value="Auto"/>
    <Setter Property="Background" Value="{DynamicResource {x:Static SystemColors.WindowBrushKey}}"/>
    <Setter Property="BorderBrush" Value="Black"/>
    <Setter Property="BorderThickness" Value="1"/>
    <Setter Property="FontFamily" Value="Arial"/>
    <Setter Property="FontSize" Value="12"/>
    <Setter Property="Foreground" Value="Black"/>
    <Setter Property="Margin" Value="0"/>
    <Setter Property="Padding" Value="0"/>
    <Setter Property="VerticalContentAlignment" Value="Center"/>
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type ComboBox}">
                <Border Background="{TemplateBinding Background}" 
                        BorderBrush="{TemplateBinding BorderBrush}" 
                        BorderThickness="{TemplateBinding BorderThickness}"
                        CornerRadius="3"
                        SnapsToDevicePixels="True">
                    <Grid>
                        <Border x:Name="Border">
                            <Popup x:Name="PART_Popup" AllowsTransparency="true" IsOpen="{TemplateBinding IsDropDownOpen}" Placement="Bottom" PopupAnimation="{DynamicResource {x:Static SystemParameters.ComboBoxPopupAnimationKey}}" Focusable="False">
                                <Border x:Name="Shdw" 
                                        MaxHeight="{TemplateBinding MaxDropDownHeight}" 
                                        MinWidth="{Binding ActualWidth, ElementName=Border}">
                                    <Border x:Name="DropDownBorder" 
                                            Background="{DynamicResource {x:Static SystemColors.WindowBrushKey}}" 
                                            BorderBrush="{TemplateBinding BorderBrush}" 
                                            BorderThickness="1">
                                        <ListView KeyboardNavigation.DirectionalNavigation="Contained"
                                                  ItemsSource="{TemplateBinding ItemsSource}"
                                                  SelectedItem="{Binding Mode=TwoWay, Path=SelectedItem, RelativeSource={RelativeSource Mode=TemplatedParent}}"
                                                  View="{TemplateBinding Tag}"/>
                                    </Border>
                                </Border>
                            </Popup>
                        </Border>
                        <DockPanel Margin="2">
                            <FrameworkElement DockPanel.Dock="Right"
                                              Width="{DynamicResource {x:Static SystemParameters.VerticalScrollBarWidthKey}}"/>
                            <Border x:Name="SelectedItemBorder" Margin="{TemplateBinding Padding}">
                                <Grid>
                                    <ContentPresenter Content="{TemplateBinding SelectionBoxItem}" 
                                                      ContentStringFormat="{TemplateBinding SelectionBoxItemStringFormat}" 
                                                      ContentTemplate="{TemplateBinding SelectionBoxItemTemplate}" 
                                                      ContentTemplateSelector="{TemplateBinding ItemTemplateSelector}"
                                                      HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" 
                                                      Margin="1,1,1,1" 
                                                      SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" 
                                                      VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
                                </Grid>
                            </Border>
                        </DockPanel>
                        <ToggleButton x:Name="DropDownToggleButton" 
                                      ClickMode="Press"
                                      Focusable="false" 
                                      Foreground="{TemplateBinding BorderBrush}"
                                      IsChecked="{Binding IsDropDownOpen, Mode=TwoWay, RelativeSource={RelativeSource TemplatedParent}}"
                                      Margin="2"
                                      MinHeight="0" 
                                      MinWidth="0" 
                                      Width="Auto"/>
                    </Grid>
                </Border>
                <ControlTemplate.Triggers>
                    <MultiTrigger>
                        <MultiTrigger.Conditions>
                            <Condition Property="IsSelectionBoxHighlighted" Value="true"/>
                            <Condition Property="IsDropDownOpen" Value="false"/>
                        </MultiTrigger.Conditions>
                        <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.HighlightTextBrushKey}}"/>
                    </MultiTrigger>
                    <Trigger Property="IsSelectionBoxHighlighted" Value="true">
                        <Setter Property="Background" TargetName="SelectedItemBorder" Value="{DynamicResource {x:Static SystemColors.HighlightBrushKey}}"/>
                    </Trigger>
                    <Trigger Property="HasItems" Value="false">
                        <Setter Property="MinHeight" TargetName="DropDownBorder" Value="95"/>
                    </Trigger>
                    <Trigger Property="IsEnabled" Value="false">
                        <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}"/>
                        <Setter Property="Background" Value="{DynamicResource {x:Static SystemColors.ControlBrushKey}}"/>
                    </Trigger>
                    <Trigger Property="IsGrouping" Value="true">
                        <Setter Property="ScrollViewer.CanContentScroll" Value="false"/>
                    </Trigger>
                    <Trigger Property="HasDropShadow" SourceName="PART_Popup" Value="true">
                        <Setter Property="Margin" TargetName="Shdw" Value="0,0,5,5"/>
                    </Trigger>
                    <Trigger Property="IsReadOnly" Value="True">
                        <Setter Property="Visibility" TargetName="DropDownToggleButton" Value="Collapsed"/>
                    </Trigger>
                </ControlTemplate.Triggers>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
    <Style.Triggers>
        <Trigger Property="IsEditable" Value="true">
            <Setter Property="IsTabStop" Value="false"/>
            <Setter Property="Padding" Value="1"/>
            <Setter Property="Template" Value="{StaticResource ComboBoxEditableTemplate}"/>
        </Trigger>
    </Style.Triggers>
</Style>

Примените вид, который вы хотите, к свойству Tag в ComboBox

<ComboBox ItemsSource={Binding Items}>
    <ComboBox.ItemTemplate>
        <DataTemplate>
            <!-- Enter your item template shown as the selected item. -->
        </DataTemplate>
    </ComboBox.ItemTemplate>
    <ComboBox.Tag>
        <GridView>
            <GridViewColumn DisplayMemberBinding="{Binding Name}"
                            Header="Name" 
                            Width="100"/>
        </GridView>
    </ComboBox.Tag>
</ComboBox>

Это все люди.

Другие вопросы по тегам