Hallo zusammen,
ich habe mal wieder eine Frage zur ComboBox aus WPF. Und zwar will ich im DropDown Menü der ComboBox zwei Informationen anzeigen, bei einer Selektion soll aber nur eine Information übernommen werden. Wie kann ich sowas umsetzen? Habe es bisher so versucht, die beiden Informationen in einen String zu packen und die hintere Information bei der Selektion einfach abzuschneiden (sind immer 4 Zeichen). Funktioniert soweit auch, nur wenn man ein zweites Mal in die ComboBox klickt, wird wieder alles ausgewält.
Gruß Fr3dd1
Was verstehst du unter "soll aber nur eine Information übernommen werden"?
Meinst du damit im GUI Angezeigt werden oder in der Logik ausgewertet werden?
Gruß
Christoph
Die Text-Property soll nur eine Information beinhalten, visuell und logisch.
Hallo Fr3dd1,
was du meinst ist mir auch nicht klar,
warum nicht eine ItemsSource an die ComboBox binden ?
Das geht über nen Templateselektor.
Du musst für aufgeklappt und für zugeklappt verschiedene Templates erstellen, und diese dann zuweisen. Hab da mal nen Artikel auf Codeproject gelesen glaub ich. Kann selbigen aber gerade leider nicht finden.
Wäre ein Converter nicht eine Lösung?
MfG
ProGamer*Der Sinn Des Lebens Ist Es, Den Sinn Des Lebens Zu Finden!
*"Wenn Unrecht zu Recht wird dann wird Widerstand zur Pflicht."
*"Ignorance simplifies ANY problem."
*"Stoppt die Piraterie der Musikindustrie"
Ein DataTemplateSelector ist die einzigste saubere Lösung, alles andere ist Gefummel und Trixerei. Genau dafür ist diese funktionalität vorhancen.
if item.IsSelected then
return ShortTemplate
else
return NormalTemplate
end if
Habe mich mal ein bischen in den TamplateSelector eingelesen aber habe noch ein Problem.
Die Templates kann ich als Resource anlegen und auch an den Selector übergeben. Ich bekomme nur die Abfrage im Selector nicht hin, wann das eine und wann das andere ausgewählt werden soll.
Momentan habe ich das so:
public override DataTemplate SelectTemplate(object item, DependencyObject container)
{
if ((item as ComboBoxItem).IsSelected)
return ClosedTemplate;
else
return OpenedTemplate;
}
Mittlerweile weis ich, das "Item" eine Zeile meines Typs ist, und kein ComboBoxItem. Wie kann ich denn jetzt abfragen ob die ComboBox geöffnet oder geschloßen ist?
Ich konnte den Selector jetzt so umschreiben, dass es zumindest keine Exception mehr gibt. Ich glaube auch das es wie folgt funktioniert:
public class SuggestTemplateSelector : DataTemplateSelector
{
public DataTemplate OpenedTemplate { get; set; }
public DataTemplate ClosedTemplate { get; set; }
public override DataTemplate SelectTemplate(object item, DependencyObject container)
{
if ((container as ContentPresenter).TemplatedParent is ComboBox)
return ClosedTemplate;
else
return OpenedTemplate;
}
}
Das einzige Problem ist nur, dass die ComboBox nicht den richtigen Wert übernimmt, sondern den Klassennamen anzeigt. Weiß jemand wie ich das noch Lösen kann?
Konnte mir auch die letzte Frage selber beantworten, die ToString() Methode der Klasse war nicht überschrieben...
Allerdings wird das Template für den geschloßenen Zustand gar nicht verwendet, kann jemand sagen warum?
Hast du OpenedTemplate und ClosedTemplate auch gesetzt?
Ich mach das immer so:
<Window.Resources>
<Controls:DetailsTemplateSelector x:Key="DetailsTemplateSelector" />
</Window.Resources>
<ComboBox ItemsSource="{Binding Items}"
ItemTemplateSelector="{StaticResource DetailsTemplateSelector}">
<ComboBox.Resources>
<DataTemplate x:Key="Opened">
<StackPanel>
<TextBlock Text="{Binding First}" />
<TextBlock Text="{Binding Second}" />
</StackPanel>
</DataTemplate>
<DataTemplate x:Key="Closed">
<TextBlock Text="{Binding First}" />
</DataTemplate>
</ComboBox.Resources>
</ComboBox>
public class DetailsTemplateSelector : DataTemplateSelector
{
public override DataTemplate SelectTemplate(object item, DependencyObject container)
{
var parent = ((FrameworkElement)container).TemplatedParent;
if (parent is ComboBox)
return ((ComboBox)parent).FindResource("Closed") as DataTemplate;
else if (parent is ComboBoxItem)
return ((ComboBoxItem)parent).FindResource("Opened") as DataTemplate;
return null;
}
}
Das tut auch, grad ma probiert.
jo, habe ich auch gemacht. Er nimmt jedoch nicht das Template sondern gibt mir einfach nur die .toString() ausgabe meines Objects zurück. Die habe ich jetzt dementsprechend angepasst.
Im geschloßenem Zustand:
DataTemplate dataTemplate = new DataTemplate();
dataTemplate.DataType = typeof(SuggestedAttributeValueInfo);
Binding binding = new Binding();
binding.Path = new PropertyPath("Unit");
FrameworkElementFactory textElement = new FrameworkElementFactory(typeof(TextBlock));
textElement.SetBinding(TextBlock.TextProperty, binding);
dataTemplate.VisualTree = textElement;
return dataTemplate;
Im geöffnetem Zustand:
DataTemplate dataTemplate = new DataTemplate();
dataTemplate.DataType = typeof(SuggestedAttributeValueInfo);
Binding binding1 = new Binding();
binding1.Path = new PropertyPath("Unit");
Binding binding2 = new Binding();
binding2.Path = new PropertyPath("Count");
MultiBinding mb = new MultiBinding();
mb.StringFormat = "{0} [{1}]";
mb.Bindings.Add(binding1);
mb.Bindings.Add(binding2);
FrameworkElementFactory textElement = new FrameworkElementFactory(typeof(TextBlock));
textElement.SetBinding(TextBlock.TextProperty, mb);
dataTemplate.VisualTree = textElement;
return dataTemplate;
Warum zum Geier machst du die Templates im Code? Sowas les ich prinzipiell nicht durch 😁
Das Ganze soll an mehreren Stellen verfügbar sein und einfach zu implementieren. Da hab ich mir die Templates einmal im Code gemacht und werden auch direkt angewandt.
Dann packs in einem Globalen "Styles" ResourceDictionary.
Einfacher als XAML geht nicht, Template im C# Code ist um Welten schlechter zu Maintainen.