2010-10-22 14 views
9

Tengo un cuadro combinado de WPF vinculado a una lista de elementos con descripciones largas.¿Cómo mostrar un valor diferente para los valores de la lista desplegable/elemento seleccionado en un WPF ComboBox?

El tipo vinculado al ComboBox tiene propiedades de descripción corta y larga. Actualmente, soy vinculante para la descripción completa.

comboBox.DisplayMemberPath = "FullDescription"; 

¿Cómo asegurar que cuando se selecciona el elemento y se muestra como un único elemento en el cuadro combinado, se muestra como un valor de la propiedad, mientras que el ShortDescription desplegable mostrará FullDescription?

Respuesta

16

actualización 2011-11-14

Hace poco vino sobre el mismo requisito de nuevo y no estaba muy contento con la solución que he publicado a continuación. Aquí hay una manera más agradable de obtener el mismo comportamiento sin volver a plantillas el ComboBoxItem. Se utiliza un DataTemplateSelector

En primer lugar, especificar la regularidad DataTemplate, en el menú desplegable DataTemplate y la ComboBoxItemTemplateSelector en los recursos para la ComboBox. Después hacer referencia a la ComboBoxItemTemplateSelector como DynamicResource para ItemTemplateSelector

<ComboBox ... 
      ItemTemplateSelector="{DynamicResource itemTemplateSelector}"> 
    <ComboBox.Resources> 
     <DataTemplate x:Key="selectedTemplate"> 
      <TextBlock Text="{Binding Path=ShortDescription}"/> 
     </DataTemplate> 
     <DataTemplate x:Key="dropDownTemplate"> 
      <TextBlock Text="{Binding Path=FullDescription}"/> 
     </DataTemplate> 
     <local:ComboBoxItemTemplateSelector 
      x:Key="itemTemplateSelector" 
      SelectedTemplate="{StaticResource selectedTemplate}" 
      DropDownTemplate="{StaticResource dropDownTemplate}"/> 
    </ComboBox.Resources> 
</ComboBox> 

ComboBoxItemTemplateSelector comprueba si el recipiente es el hijo de un ComboBoxItem, si lo es, entonces se trata de un elemento desplegable, de lo contrario, es el elemento de la ComboBox.

public class ComboBoxItemTemplateSelector : DataTemplateSelector 
{ 
    public DataTemplate DropDownTemplate 
    { 
     get; 
     set; 
    } 
    public DataTemplate SelectedTemplate 
    { 
     get; 
     set; 
    } 
    public override DataTemplate SelectTemplate(object item, DependencyObject container) 
    { 
     ComboBoxItem comboBoxItem = VisualTreeHelpers.GetVisualParent<ComboBoxItem>(container); 
     if (comboBoxItem != null) 
     { 
      return DropDownTemplate; 
     } 
     return SelectedTemplate; 
    } 
} 

GetVisualParent

public static T GetVisualParent<T>(object childObject) where T : Visual 
{ 
    DependencyObject child = childObject as DependencyObject; 
    while ((child != null) && !(child is T)) 
    { 
     child = VisualTreeHelper.GetParent(child); 
    } 
    return child as T; 
} 

solución Viejo, requiere re-plantillas de ComboBoxItem

<SolidColorBrush x:Key="SelectedBackgroundBrush" Color="#DDD" /> 
<SolidColorBrush x:Key="DisabledForegroundBrush" Color="#888" /> 

<ControlTemplate x:Key="FullDescriptionTemplate" TargetType="ComboBoxItem"> 
    <Border Name="Border" Padding="2" SnapsToDevicePixels="true"> 
     <StackPanel> 
      <TextBlock Text="{Binding Path=FullDescription}"/> 
     </StackPanel> 
    </Border> 
    <ControlTemplate.Triggers> 
     <Trigger Property="IsHighlighted" Value="true"> 
      <Setter TargetName="Border" Property="Background" Value="{StaticResource SelectedBackgroundBrush}"/> 
     </Trigger> 
     <Trigger Property="IsEnabled" Value="false"> 
      <Setter Property="Foreground" Value="{StaticResource DisabledForegroundBrush}"/> 
     </Trigger> 
    </ControlTemplate.Triggers> 
</ControlTemplate> 

<ComboBox Name="c_comboBox" ItemsSource="{Binding}"> 
    <ComboBox.ItemTemplate> 
     <DataTemplate> 
      <TextBlock Text="{Binding Path=ShortDescription}"/> 
     </DataTemplate> 
    </ComboBox.ItemTemplate> 
    <ComboBox.ItemContainerStyle> 
     <Style TargetType="{x:Type ComboBoxItem}"> 
      <Setter Property="Template" Value="{StaticResource FullDescriptionTemplate}" /> 
     </Style> 
    </ComboBox.ItemContainerStyle> 
</ComboBox> 

Esto se traduce en el siguiente comportamiento

alt text

+0

Gracias! Como todo en WPF, ... todo es posible, pero a veces hay muchas líneas en XAML :) – Marek

+2

¿Has visto [este método] (http://stackoverflow.com/a/8279344/546730)? –

+0

opción seleccionada no se muestra correctamente. En su lugar, se muestra el nombre de la propiedad de clase completamente calificado (según la nueva solución) –

0

Otra opción que he encontrado es colocar un cuadro de texto sobre el área de texto del cuadro combinado. Tamaño y alinear de forma que quede perfectamente sobre ella a continuación, utilizar un sub similar a esto:

Private Sub ComboBox*_Change() 
Dim T As String 
T = Left(ComboBox*.Text, 1) 
TextBox*.Value = T 
End Sub 

(reemplazar el * con los números correspondientes) el resultado es que cuando se selecciona el menú desplegable mostrará la lista como de costumbre pero el cuadro de texto que se encuentra sobre él solo mostrará su primer carácter.

Espero que esto ayude.

2

No parece funcionar para mí ahora, pero esto se hace:

public class ComboBoxItemTemplateSelector : DataTemplateSelector { 
    public DataTemplate SelectedTemplate { get; set; } 
    public DataTemplate DropDownTemplate { get; set; } 

    public override DataTemplate SelectTemplate(object item, DependencyObject container) { 
    var presenter = (ContentPresenter)container; 
    return (presenter.TemplatedParent is ComboBox) ? SelectedTemplate : DropDownTemplate; 
    } 
} 
Cuestiones relacionadas