2010-10-22 4 views
9

Ich habe eine WPF-Combobox an eine Liste von Elementen mit langen Beschreibungen gebunden.Wie wird ein anderer Wert für Dropdown-Listenwerte/ausgewähltes Element in einer WPF-ComboBox angezeigt?

Der an die ComboBox gebundene Typ hat kurze und lange Beschreibung als Eigenschaften. Zur Zeit bin ich an die vollständige Beschreibung gebunden.

comboBox.DisplayMemberPath = "FullDescription"; 

Wie kann sichergestellt werden, dass, wenn das Element ausgewählt ist und als ein einzelnes Element in der Combobox angezeigt, wird es als Wert der ShortDescription Eigenschaft angezeigt werden, während das Drop-Down-FullDescription angezeigt wird?

Antwort

16

-Update 2011-11-14

Ich kam vor kurzem auf die gleiche Anforderung wieder und ich war nicht sehr zufrieden mit der Lösung, die ich unten geschrieben. Hier ist eine bessere Möglichkeit, das gleiche Verhalten zu erhalten, ohne die ComboBoxItem neu zu erstellen. Es verwendet ein DataTemplateSelector

Zuerst die regelmäßige DataTemplate angeben, die Drop-Down-DataTemplate und die ComboBoxItemTemplateSelector in den Ressourcen für die ComboBox. Dann verweisen auf die ComboBoxItemTemplateSelector als DynamicResource für 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 überprüft, ob der Behälter das Kind eines ComboBoxItem ist, wenn es ist, dann sind wir mit einem Drop-Down-Artikel zu tun, sonst ist es das Element in der 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; 
} 

Alte Lösung erfordert Re-Templat von 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> 

Dies ergibt sich folgendes Verhalten

alt text

+0

Dank! Wie alles in WPF, ... ist alles möglich, aber manchmal sind es viele Zeilen in XAML :) – Marek

+2

Hast du [diese Methode] gesehen (http://stackoverflow.com/a/8279344/546730)? –

+0

ausgewählte Option wird nicht richtig angezeigt. Stattdessen wird der Name der vollständig qualifizierten Klasseneigenschaft angezeigt (gemäß neuer Lösung) –

0

Eine andere Option, die ich gefunden habe, ist, eine Textbox über den Textbereich der Combobox zu platzieren. Größe und so ausrichten, dass sie legt perfekt über es dann ein Unter ähnlich verwenden, um diese:

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

(ersetzen die * mit den entsprechenden Zahlen) das Ergebnis ist, dass, wenn die Drop-Down-Auswahl wird die Liste wie gewohnt angezeigt werden aber das darüber liegende Textfeld zeigt nur sein erstes Zeichen.

Hoffe, das hilft.

2

Es scheint nicht, jetzt für mich zu arbeiten, aber dies tut:

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; 
    } 
} 
Verwandte Themen