Willkommen auf myCSharp.de! Anmelden | kostenlos registrieren
 | Suche | FAQ

Hauptmenü
myCSharp.de
» Startseite
» Forum
» Suche
» Regeln
» Wie poste ich richtig?

Mitglieder
» Liste / Suche
» Wer ist online?

Ressourcen
» FAQ
» Artikel
» C#-Snippets
» Jobbörse
» Microsoft Docs

Team
» Kontakt
» Cookies
» Spenden
» Datenschutz
» Impressum

  • »
  • Community
  • |
  • Diskussionsforum
ComboBox - nicht alles aus DropDown übernehmen
Fr3dd1
myCSharp.de - Member



Dabei seit:
Beiträge: 106

Themenstarter:

ComboBox - nicht alles aus DropDown übernehmen

beantworten | zitieren | melden

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
private Nachricht | Beiträge des Benutzers
Christoph K.
myCSharp.de - Member

Avatar #avatar-3248.png


Dabei seit:
Beiträge: 817
Herkunft: Köln

beantworten | zitieren | melden

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
private Nachricht | Beiträge des Benutzers
Fr3dd1
myCSharp.de - Member



Dabei seit:
Beiträge: 106

Themenstarter:

beantworten | zitieren | melden

Die Text-Property soll nur eine Information beinhalten, visuell und logisch.
private Nachricht | Beiträge des Benutzers
Zicore
myCSharp.de - Member



Dabei seit:
Beiträge: 403

beantworten | zitieren | melden

Hallo Fr3dd1,

was du meinst ist mir auch nicht klar,
warum nicht eine ItemsSource an die ComboBox binden ?
private Nachricht | Beiträge des Benutzers
TomLeech
myCSharp.de - Member



Dabei seit:
Beiträge: 146

beantworten | zitieren | melden

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.
private Nachricht | Beiträge des Benutzers
ProGamer
myCSharp.de - Member



Dabei seit:
Beiträge: 660
Herkunft: NRW

beantworten | zitieren | melden

Wäre ein Converter nicht eine Lösung?
MfG
ProGamer
private Nachricht | Beiträge des Benutzers
userid14268
myCSharp.de - Member



Dabei seit:
Beiträge: 1.578

beantworten | zitieren | melden

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
Dieser Beitrag wurde 1 mal editiert, zum letzten Mal von userid14268 am .
private Nachricht | Beiträge des Benutzers
Fr3dd1
myCSharp.de - Member



Dabei seit:
Beiträge: 106

Themenstarter:

beantworten | zitieren | melden

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?
private Nachricht | Beiträge des Benutzers
Fr3dd1
myCSharp.de - Member



Dabei seit:
Beiträge: 106

Themenstarter:

beantworten | zitieren | melden

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?
private Nachricht | Beiträge des Benutzers
Fr3dd1
myCSharp.de - Member



Dabei seit:
Beiträge: 106

Themenstarter:

beantworten | zitieren | melden

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?
private Nachricht | Beiträge des Benutzers
userid14268
myCSharp.de - Member



Dabei seit:
Beiträge: 1.578

beantworten | zitieren | melden

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.
private Nachricht | Beiträge des Benutzers
Fr3dd1
myCSharp.de - Member



Dabei seit:
Beiträge: 106

Themenstarter:

beantworten | zitieren | melden

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.
private Nachricht | Beiträge des Benutzers
userid14268
myCSharp.de - Member



Dabei seit:
Beiträge: 1.578

beantworten | zitieren | melden

Wie sehn deine Templates aus?
private Nachricht | Beiträge des Benutzers
Fr3dd1
myCSharp.de - Member



Dabei seit:
Beiträge: 106

Themenstarter:

beantworten | zitieren | melden

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;
private Nachricht | Beiträge des Benutzers
userid14268
myCSharp.de - Member



Dabei seit:
Beiträge: 1.578

beantworten | zitieren | melden

Warum zum Geier machst du die Templates im Code? Sowas les ich prinzipiell nicht durch
private Nachricht | Beiträge des Benutzers
Fr3dd1
myCSharp.de - Member



Dabei seit:
Beiträge: 106

Themenstarter:

beantworten | zitieren | melden

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.
private Nachricht | Beiträge des Benutzers
userid14268
myCSharp.de - Member



Dabei seit:
Beiträge: 1.578

beantworten | zitieren | melden

Dann packs in einem Globalen "Styles" ResourceDictionary.
Einfacher als XAML geht nicht, Template im C# Code ist um Welten schlechter zu Maintainen.
private Nachricht | Beiträge des Benutzers