2010-09-08 15 views
15

Este es mi cuadro combinado.WPF Combobox: Plantilla diferente en el cuadro de texto y en la lista desplegable

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

cómo puedo cambiar para que sólo el NombreCompleto aparece en la parte de texto de la lista desplegable, mientras que las tres columnas siguen apareciendo en la parte desplegable?

Respuesta

26

Desafortunadamente, el SelectionBoxItemTemplate es una propiedad de solo lectura, por lo que tenemos que trabajar un poco más. Al hacer que ItemTemplate sea la forma en que desea que aparezca el elemento cuando se selecciona, puede editar el ItemContainerStyle para proporcionar un ControlTemplate que incluye los otros campos que desea mostrar.

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

Para la plantilla ComboBoxItem, que acaba de modificar el predeterminado, por lo que debe ser completamente funcional.

+0

Me va a llevar mucho tiempo entender completamente lo que hizo, pero funciona como se anuncia. –

+0

Han pasado algunos años, pero esta respuesta fue útil para mí. +1 –

8

Si la propiedad IsEditable de ComboBox se establece en True, puede establecer la propiedad "TextSearch.TextPath" del ComboBox en el nombre de la propiedad que desea mostrar. Así, en su caso:

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

Eso rompe TextSearch. –

+1

¿Qué quieres decir con que "rompe" TextSearch? – ASanch

2

En lugar de utilizar la propiedad de sólo lectura SelectionBoxItemTemplate he creado una nueva (que se adjunta, se puede escribir) y se utiliza la propiedad que uno de mi estilo. También he añadido un disparador para mi estilo para no romper todos los cuadros combinados que no están utilizando mi nueva propiedad adjunta ...

utilizar de esta manera:

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

Sólo tienes que añadir esta clase a su proyecto:

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); 
    } 

} 

y cambiar su estilo de ComboBox para utilizar la propiedad adjunta SelectionBoxAltTemplate Si se establece (o porque no podía establecer un disparador para "no nulo", me puse de nuevo a la SelectionBoxItemTemplate defecto si el adjunto es nulo):

El ContentPresenter dentro del ControlTemplate del estilo de ComboBox:

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

y el disparador para proporcionar compatibilidad hacia atrás a ComboBoxed sin la propiedad adjunta:

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

completo Estilo:

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

Sin embargo, es posible que esto no funcione con ItemTemplateSelctors, solo con una sola plantilla, pero puede agregar fácilmente una propiedad adjunta "SelectionBoxAltTemplateSelector" que proporciona el selector y lo pasa al estilo.

1

Hay una muy buena respuesta a su pregunta aquí si no desea cambiar el estilo ComboBoxes: https://stackoverflow.com/a/2277488/1070906

Se utiliza un disparador en el DataTemplate que se ve si hay un ComboBoxItem algún lugar por encima de la calidad visual árbol, que no es el caso en el cuadro de selección.

Cuestiones relacionadas