2010-09-08 117 views
15

这是我的组合框。WPF Combobox:文本框和下拉列表中的不同模板

<ComboBox Height="45" HorizontalAlignment="Left" Margin="184,66,0,0" Name="ComboBox1" VerticalAlignment="Top" Width="216"> 
     <ComboBox.ItemTemplate> 
      <DataTemplate> 
       <StackPanel Orientation="Horizontal"> 
        <Label Content="{Binding FullName}" Width="150" /> 
        <Label Content="{Binding Title}" Width="100"/> 
        <Label Content="{Binding BranchName}" /> 
       </StackPanel> 
      </DataTemplate> 
     </ComboBox.ItemTemplate> 
    </ComboBox> 

我如何改变它,这样只有全名出现在组合框的文本框部分,而所有三个栏仍显示在下拉部分?

回答

26

不幸的是,SelectionBoxItemTemplate是只读属性,所以我们必须做更多的工作。通过使ItemTemplate成为您希望项目在选定时出现的方式,您可以编辑ItemContainerStyle以提供包含您要显示的其他字段的ControlTemplate

<ComboBox Height="45" HorizontalAlignment="Left" Margin="184,66,0,0" Name="ComboBox1" VerticalAlignment="Top" Width="216"> 
    <ComboBox.ItemTemplate> 
     <DataTemplate> 
      <Label Content="{Binding FullName}" Width="150" /> 
     </DataTemplate> 
    </ComboBox.ItemTemplate> 
    <ComboBox.ItemContainerStyle> 
     <Style TargetType="{x:Type ComboBoxItem}"> 
      <Setter Property="Template"> 
       <Setter.Value> 
        <ControlTemplate TargetType="{x:Type ComboBoxItem}"> 
         <Border x:Name="Bd" 
           BorderBrush="{TemplateBinding BorderBrush}" 
           BorderThickness="{TemplateBinding BorderThickness}" 
           Background="{TemplateBinding Background}"> 
          <StackPanel Orientation="Horizontal"> 
           <ContentPresenter HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" 
                VerticalAlignment="{TemplateBinding VerticalContentAlignment}" /> 
           <Label Content="{Binding Title}" Width="100"/> 
           <Label Content="{Binding BranchName}" /> 
          </StackPanel> 
         </Border> 
         <ControlTemplate.Triggers> 
          <Trigger Property="IsHighlighted" Value="True"> 
           <Setter TargetName="Bd" Property="Background" Value="{DynamicResource {x:Static SystemColors.HighlightBrushKey}}" /> 
           <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.HighlightTextBrushKey}}" /> 
          </Trigger> 
          <Trigger Property="IsEnabled" Value="False"> 
           <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}" /> 
          </Trigger> 
         </ControlTemplate.Triggers> 
        </ControlTemplate> 
       </Setter.Value> 
      </Setter> 
     </Style> 
    </ComboBox.ItemContainerStyle> 
</ComboBox> 

对于ComboBoxItem模板,我只是修改了默认的,所以它应该是全功能的。

+0

需要很长时间才能完全理解你做了什么,但它确实按照广告的方式工作。 – 2010-09-08 22:21:35

+0

已经有几年了,但这个答案对我很有用。 +1 – 2013-10-08 20:26:13

8

如果ComboBox的IsEditable属性设置为True,则可以将ComboBox的“TextSearch.TextPath”属性设置为要显示的属性名称。所以你的情况:

<ComboBox IsEditable="True" TextSearch.TextPath="FullName" .../> 
+0

这打破了TextSearch。 – 2010-09-08 22:12:37

+1

你是什么意思它“打破”TextSearch? – ASanch 2010-09-08 22:39:48

2

使用我创建了一个新的(附后,可写的)财产,使用了一个在我的风格只读SelectionBoxItemTemplate属性,而不是。我还添加了一个触发我的风格不打破不使用我的新附加属性的组合框的所有...

使用方法如下:

<ComboBox ItemsSource="{Binding ...}" SelectedItem="{Binding ..., Mode=TwoWay}"> 
    <controls:ComboBoxSelectionBoxAltTemplateBehaviour.SelectionBoxAltTemplate> 
     <DataTemplate DataType="{x:Type ...}"> 
      ... Template for the selection box ... 
     </DataTemplate> 
    </controls:ComboBoxSelectionBoxAltTemplateBehaviour.SelectionBoxAltTemplate> 
    <ComboBox.ItemTemplate> 
     <DataTemplate DataType="{x:Type ...}"> 
      ... Template for the popup ... 
     </DataTemplate> 
    </ComboBox.ItemTemplate> 
</ComboBox> 

你只需要这一类添加到您的项目:

public class ComboBoxSelectionBoxAltTemplateBehaviour 
{ 
    public static readonly DependencyProperty SelectionBoxAltTemplateProperty = DependencyProperty.RegisterAttached(
     "SelectionBoxAltTemplate", typeof (DataTemplate), typeof (ComboBoxSelectionBoxAltTemplateBehaviour), new PropertyMetadata(default(DataTemplate))); 

    public static void SetSelectionBoxAltTemplate(DependencyObject element, DataTemplate value) 
    { 
     element.SetValue(SelectionBoxAltTemplateProperty, value); 
    } 

    public static DataTemplate GetSelectionBoxAltTemplate(DependencyObject element) 
    { 
     return (DataTemplate) element.GetValue(SelectionBoxAltTemplateProperty); 
    } 

} 

,改变你的组合框样式使用SelectionBoxAltTemplate附加属性如果设置(或因为我无法触发设置为“不空”,我把它设回默认SelectionBoxItemTemplate如果附加一个是null):

组合框样式的控件模板内的ContentPresenter:

<ContentPresenter Content="{TemplateBinding SelectionBoxItem}" ContentTemplate="{TemplateBinding controls:ComboBoxSelectionBoxAltTemplateBehaviour.SelectionBoxAltTemplate}" /> 

和触发提供向后兼容ComboBoxed没有附加属性:

<ControlTemplate.Triggers> 
    <Trigger Property="controls:ComboBoxSelectionBoxAltTemplateBehaviour.SelectionBoxAltTemplate" Value="{x:Null}"> 
     <Setter Property="ContentTemplate" Value="{Binding SelectionBoxItemTemplate, RelativeSource={RelativeSource TemplatedParent}}" TargetName="ContentSite" /> 
    </Trigger> 
    ... 
</ControlTemplate.Triggers> 

尽显风采:

<Style x:Key="{x:Type ComboBox}" TargetType="{x:Type ComboBox}"> 
    <Setter Property="SnapsToDevicePixels" Value="true" /> 
    <Setter Property="HorizontalContentAlignment" Value="Stretch" /> 
    <Setter Property="VerticalContentAlignment" Value="Center" /> 
    <Setter Property="FontSize" Value="12" /> 
    <Setter Property="Background" Value="{StaticResource ComboBoxBackground}"/> 
    <Setter Property="BorderBrush" Value="{StaticResource ComboBoxBorder}"/> 
    <Setter Property="Margin" Value="6"/> 
    <Setter Property="Padding" Value="3,3,5,3"/> 
    <Setter Property="Template"> 
     <Setter.Value> 
      <ControlTemplate TargetType="{x:Type ComboBox}"> 
       <Grid> 
        <Grid.ColumnDefinitions>      
         <ColumnDefinition Width="*"/> 
         <ColumnDefinition Width="Auto"/> 
        </Grid.ColumnDefinitions> 
        <Border Name="Border" Grid.ColumnSpan="2" Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}"/> 
        <ToggleButton Name="ToggleButton2" Focusable="False" IsChecked="{Binding Path=IsDropDownOpen, Mode=TwoWay, RelativeSource={RelativeSource TemplatedParent}}" ClickMode="Press" Grid.ColumnSpan="2" Background="Transparent"/> 
        <!-- Allows clicking anywhere on the combobox, not only the visible button on the right --> 
        <ToggleButton Focusable="false" Grid.Column="1" x:Name="ToggleButton" IsChecked="{Binding Path=IsDropDownOpen, Mode=TwoWay, RelativeSource={RelativeSource TemplatedParent}}" ClickMode="Press" Style="{StaticResource ComboBoxToggleButton}"/> 
        <ContentPresenter HorizontalAlignment="Left" Margin="{TemplateBinding Control.Padding}" x:Name="ContentSite" VerticalAlignment="Center" Content="{TemplateBinding SelectionBoxItem}" ContentTemplate="{TemplateBinding controls:ComboBoxSelectionBoxAltTemplateBehaviour.SelectionBoxAltTemplate}" ContentTemplateSelector="{TemplateBinding ItemTemplateSelector}" IsHitTestVisible="False" /> 

        <TextBox Visibility="Hidden" HorizontalAlignment="Left" Margin="{TemplateBinding Control.Padding}" x:Name="PART_EditableTextBox" Style="{x:Null}" VerticalAlignment="Center" Focusable="True" Background="Transparent" /> 

        <Popup IsOpen="{TemplateBinding IsDropDownOpen}" Placement="Bottom" x:Name="Popup" Focusable="False" AllowsTransparency="True" PopupAnimation="Slide"> 
         <Grid MaxHeight="{TemplateBinding MaxDropDownHeight}" MinWidth="{TemplateBinding ActualWidth}" x:Name="DropDown" SnapsToDevicePixels="True"> 
          <Border x:Name="DropDownBorder" Background="{StaticResource ComboBoxBackground}" BorderBrush="{StaticResource ComboBoxBorder}" BorderThickness="1" Padding="0,4"> 
           <ScrollViewer SnapsToDevicePixels="True" HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Auto" CanContentScroll="True" Style="{x:Null}" > 
            <StackPanel IsItemsHost="True" KeyboardNavigation.DirectionalNavigation="Contained"/> 
           </ScrollViewer> 
          </Border> 
         </Grid> 
        </Popup> 
       </Grid> 
       <ControlTemplate.Triggers> 
        <Trigger Property="controls:ComboBoxSelectionBoxAltTemplateBehaviour.SelectionBoxAltTemplate" Value="{x:Null}"> 
         <Setter Property="ContentTemplate" Value="{Binding SelectionBoxItemTemplate, RelativeSource={RelativeSource TemplatedParent}}" TargetName="ContentSite" /> 
        </Trigger> 
        <Trigger Property="HasItems" Value="false"> 
         <Setter Property="MinHeight" Value="95" TargetName="DropDownBorder" /> 
        </Trigger> 
        <Trigger Property="IsGrouping" Value="true"> 
         <Setter Property="ScrollViewer.CanContentScroll" Value="false" /> 
        </Trigger> 
        <Trigger Property="IsEditable" Value="true"> 
         <Setter Property="IsTabStop" Value="false" /> 
         <Setter Property="Visibility" Value="Visible" TargetName="PART_EditableTextBox" /> 
         <Setter Property="Visibility" Value="Hidden" TargetName="ContentSite" /> 
        </Trigger> 

        <Trigger Property="IsMouseOver" Value="true" SourceName="ToggleButton2"> 
         <Setter Property="Background" Value="{StaticResource ComboBoxMouseOver}" /> 
        </Trigger> 
        <Trigger Property="HasItems" Value="False"> 
         <Setter Property="IsEnabled" Value="False"/> 
        </Trigger> 
       </ControlTemplate.Triggers> 
      </ControlTemplate> 
     </Setter.Value> 
    </Setter> 
</Style> 

但是,这可能不适用于ItemTemplateSelctors,只能使用一个模板 - 但你可以很容易地添加一个附加属性“SelectionBoxAltTemplateSelector”,它提供了选择器并将其传递给样式。

1

有一个很好的答案,在这里你的问题,如果你不想改变组合框样式:https://stackoverflow.com/a/2277488/1070906

它采用了触发的,看起来如果有一个以上ComboBoxItem在视觉上某处的DataTemplate树,在选择框中不是这种情况。

相关问题