带标题的多项组合框?

时间:2011-04-27 17:10:54

标签: wpf xaml combobox header

是否可以在组合框上绑定多个项目的“列标题”?例如,显示人名的组合框。组合框将显示John Doe。但是我想显示列标题:

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>      

5 个答案:

答案 0 :(得分:16)

示例:

<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可以依赖,ElementNameRelativeSource不起作用,是因为CompositeCollection只是一个集合,而不是FrameworkElement。

除此之外,这样做的方法是通过具有共享大小列的网格。 DataTemplate通过DataType自动应用。

screenshot

编辑:将标题-ComboBoxItem的IsHitTestVisible属性设置为False是不够的,因为仍然可以使用键盘选择它。我现在将其更改为IsEnabled="False",稍微淡化了该项目。您可能可能会重新模板该项目而不是这样做。或者,如果你发现另一种方法可以从选择中禁用它,那当然也可以解决。

答案 1 :(得分:2)

将列标题添加到组合框的最简单方法是在组合框中使用listview。 以下代码为其提供了解决方案。

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

答案 2 :(得分:0)

将以下样式应用于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>

将您想要的视图应用于ComboBox的Tag属性

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

多数民众议员。

答案 3 :(得分:0)

我喜欢H.B.'s answer,但不幸的是,当我使用它时,我会在标头ComboBoxItem的{​​{1}}和HorizontalContentAlignment属性的输出中看到数据绑定错误:

  

找不到引用'RelativeSource的绑定源   FindAncestor,AncestorType ='System.Windows.Controls.ItemsControl',   AncestorLevel = '1'”。 BindingExpression:路径= Horizo​​ntalContentAlignment;   的DataItem = NULL; target元素是'ComboBoxItem'(Name ='');目标   property是'Horizo​​ntalContentAlignment'(类型'Horizo​​ntalAlignment')

这些不会使程序崩溃,但是它们会使输出混乱,并在运行调试版本时导致可察觉的延迟。无论是什么导致它们似乎都在VerticalContentAlignmentComboBox的深处;在任何情况下,我都无法找到任何方法来阻止它们(手动或通过ComboBoxItem设置这些属性没有帮助)。所以我最终会略有变化。这比我喜欢的东西更长,更黑,但它完成了工作:

Style

答案 4 :(得分:0)

我喜欢Nandha的回答,因为这就是我想要实现的目标。但是,组合框的文本字段将无法正常工作。

由于我很懒,所以为了解决这个问题,我创建了一个水平方向的StackPanel,将一个TextBox绑定到所选项目的字段上,并使用带有嵌入式ListView的Combo Box。现在,组合框的宽度为20,因此仅显示向下箭头(您可以使用宽度和边距来获得正确的外观。这使文本框看起来像一个组合框,具有ListView的所有优点,以及更少的编码。

我希望这会有所帮助。enter image description here