2010-10-22 4 views
9

J'ai une liste déroulante WPF liée à une liste d'éléments avec des descriptions longues.Comment afficher une valeur différente pour les valeurs de la liste déroulante/l'élément sélectionné dans un WPF ComboBox?

Le type lié à la zone de liste déroulante possède des descriptions courtes et longues en tant que propriétés. Actuellement, je suis lié à la description complète.

comboBox.DisplayMemberPath = "FullDescription"; 

Comment faire en sorte que lorsque l'élément est sélectionné et affiché sous la forme d'un seul élément dans la liste déroulante, il sera affiché en tant que valeur de la propriété ShortDescription alors que le menu déroulant affiche FullDescription?

Répondre

16

Mise à jour 2011-11-14

Je suis récemment tombé sur la même exigence encore et je n'étais pas très satisfait de la solution que j'ai posté ci-dessous. Voici une meilleure façon d'obtenir le même comportement sans reformater le ComboBoxItem. Il utilise un DataTemplateSelector

D'abord, spécifiez le DataTemplate régulier, le menu déroulant DataTemplate et le ComboBoxItemTemplateSelector des ressources pour le ComboBox. Ensuite, faire référence à la ComboBoxItemTemplateSelector comme DynamicResource pour 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 vérifie si le conteneur est l'enfant d'un ComboBoxItem, si elle est, nous avons affaire à un élément de menu déroulant, sinon il est l'élément dans 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; 
} 

Ancienne solution, il faut re-templating 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> 

Il en résulte le comportement suivant

alt text

+0

Merci! Comme tout dans WPF, ... tout est possible, mais parfois c'est beaucoup de lignes en XAML :) – Marek

+2

Avez-vous vu [cette méthode] (http://stackoverflow.com/a/8279344/546730)? –

+0

L'option sélectionnée n'est pas affichée correctement. Au lieu de cela, le nom complet de la propriété de classe est affiché (selon la nouvelle solution) –

0

Une autre option que j'ai trouvée est de placer une zone de texte sur la zone de texte de liste déroulante. La taille et l'aligner de sorte qu'il repose parfaitement sur elle utilise alors un sous semblable à ceci:

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

(remplacez * par les numéros correspondants) le résultat est que quand il est sélectionné dans le menu déroulant affiche la liste comme d'habitude mais la zone de texte qui se trouve dessus ne montrera que son premier caractère.

Espérons que cela aide.

2

Il ne semble pas fonctionner pour moi maintenant, mais celui-ci fait:

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; 
    } 
} 
Questions connexes