none
ComboBox.SelectedItem an Property Binden RRS feed

  • Frage

  • High Peoples,

    ich habe mal ein bisschen gesucht und bin leider noch nicht so richtig fündig geworden. Da ich noch nicht so richtig fit bin, hoffe ich auf Nachsicht und Hilfe.

    Eine ComboBox habe ich an eine Liste<Genre> gebunden. Ein Selected Item (zB "Rock") an eine Property. DiesePropterty ist wiederum an ein TextBlock gebunden. Ich habe wohl noch nicht alles berücksichtigt, denn zwar wird was im TextBlock angezeigt, wenn ich was in der ComboBox selektiere (zB "Rock"), jedoch wird dann "Rock" nicht im TextBlock angezeigt sondern "WpfApplication3.Genre".

    Nun könnte ich zwar in der Code-Behind das erledigen, jedoch würde ich das lieber per XAML das machen (wenn überhaupt möglich). Wenn es nur per XAML gehen sollte, bin ich für einen kleinen Tip sehr dankbar.

    regards: Mirko

    (kein Code mitgeschickt, da ich eigentlich nur wissen möchte, ob das nur per XAML gehen würde.....kann aber natürlich betreffenden Ausschnitt dann im Nachhinein noch posten).

    Mittwoch, 4. Dezember 2013 18:30

Antworten

  • Hallo,
    das Problem dabei ist, das im TextBlock einfach ausgewähltesGenre.ToString() aufruft und das erzeugt standardmäßig den Namen der Klasse. Also entweder...

    ...überschreibst du die Methode:

            public override string ToString()
            {
                return this.GenreName;
            }
    oder
    ...passt die XAML-Bindung an:
    <TextBlock Text="{Binding SelectedGenre.GenreName}" 
    Ich bin davon ausgegangen, das deine Klassen in etwa wie folgt aussehen:
        public partial class MainWindow : Window, INotifyPropertyChanged
        {
            public MainWindow()
            {
                this.Items = new ObservableCollection<Genre>();
                this.Items.Add(new Genre() { GenreName = "Rock 1" });
                this.Items.Add(this.SelectedGenre = new Genre() { GenreName = "Rock 2" });
                this.Items.Add(new Genre() { GenreName = "Rock 3" });
                InitializeComponent();
                this.DataContext = this;
            }

            public Genre _SelectedGenre;
            public Genre SelectedGenre
            {
                get
                {
                    return this._SelectedGenre;
                }
                set
                {
                    if(this._SelectedGenre!=value)
                    {
                        this._SelectedGenre = value;
                        this.OnPropertyChanged("SelectedGenre");//Änderung der Eigenschaft an das Fenster übermitteln
                    }
                }
            }

            public ObservableCollection<Genre> Items { get; set; }
           
            protected virtual void OnPropertyChanged(string propName)
            {
                var evt = this.PropertyChanged;
                if (evt != null)
                    evt(this, new PropertyChangedEventArgs(propName));
            }

            public event PropertyChangedEventHandler PropertyChanged;
        }

        public class Genre
        {
            public string GenreName { get; set; }
        }
    Der gesamte XAML-Code lautet bei mir:
    <Window x:Class="WpfApplication9.MainWindow"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            Title="MainWindow" Height="350" Width="525">
        <Grid>
            <ComboBox SelectedItem="{Binding SelectedGenre, Mode=TwoWay}" Name="cb" ItemsSource="{Binding Items}" DisplayMemberPath="GenreName" 
                      HorizontalAlignment="Left" Margin="162,96,0,0" VerticalAlignment="Top" Width="120"/>
            <TextBlock Text="{Binding SelectedGenre.GenreName}" HorizontalAlignment="Left" Margin="152,210,0,0" TextWrapping="Wrap" VerticalAlignment="Top"/>
        </Grid>
    </Window>





    Koopakiller [kuːpakɪllɐ] (Tom Lambert)
    Webseite | Code Beispiele | Facebook | Twitter | Snippets   C# ↔ VB.NET Konverter
    Markiert bitte beantwortende Posts als Antwort und bewertet Beiträge. Danke.

    Mittwoch, 4. Dezember 2013 18:57
    Moderator
  • Hi....,

    herzlichen Dank für deine Antworten. Ich habe etwas nicht gewusst........"SelectedValuePath"

    <TextBlock Text="{Binding Source={StaticResource Con},
                Path=Genre, (Property in Klasse Control)
                Mode=OneWay}"/>

    <ComboBox x:Name="cmbBoxGenre" ItemsSource="{Binding}" DisplayMemberPath="Description" SelectedValuePath="Description" SelectedValue="{Binding Source={StaticResource Con}, Path=Genre, (Property in Classe Control) Mode=OneWayToSource}" />

    <Button Content="Load" Click="Button_Click" /> (this.cmmBoxGenre.DataSource =

    control.LoadGenre(conDB);

    nochmal recht herzlichen Dank für deine Mühe. Hab schon einige Male Fragen gepostet und immer wieder aufschlussreiche Antworten bekommen. Ne coole Sache hier......


    Mittwoch, 4. Dezember 2013 21:30

Alle Antworten

  • Hallo,
    das Problem dabei ist, das im TextBlock einfach ausgewähltesGenre.ToString() aufruft und das erzeugt standardmäßig den Namen der Klasse. Also entweder...

    ...überschreibst du die Methode:

            public override string ToString()
            {
                return this.GenreName;
            }
    oder
    ...passt die XAML-Bindung an:
    <TextBlock Text="{Binding SelectedGenre.GenreName}" 
    Ich bin davon ausgegangen, das deine Klassen in etwa wie folgt aussehen:
        public partial class MainWindow : Window, INotifyPropertyChanged
        {
            public MainWindow()
            {
                this.Items = new ObservableCollection<Genre>();
                this.Items.Add(new Genre() { GenreName = "Rock 1" });
                this.Items.Add(this.SelectedGenre = new Genre() { GenreName = "Rock 2" });
                this.Items.Add(new Genre() { GenreName = "Rock 3" });
                InitializeComponent();
                this.DataContext = this;
            }

            public Genre _SelectedGenre;
            public Genre SelectedGenre
            {
                get
                {
                    return this._SelectedGenre;
                }
                set
                {
                    if(this._SelectedGenre!=value)
                    {
                        this._SelectedGenre = value;
                        this.OnPropertyChanged("SelectedGenre");//Änderung der Eigenschaft an das Fenster übermitteln
                    }
                }
            }

            public ObservableCollection<Genre> Items { get; set; }
           
            protected virtual void OnPropertyChanged(string propName)
            {
                var evt = this.PropertyChanged;
                if (evt != null)
                    evt(this, new PropertyChangedEventArgs(propName));
            }

            public event PropertyChangedEventHandler PropertyChanged;
        }

        public class Genre
        {
            public string GenreName { get; set; }
        }
    Der gesamte XAML-Code lautet bei mir:
    <Window x:Class="WpfApplication9.MainWindow"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            Title="MainWindow" Height="350" Width="525">
        <Grid>
            <ComboBox SelectedItem="{Binding SelectedGenre, Mode=TwoWay}" Name="cb" ItemsSource="{Binding Items}" DisplayMemberPath="GenreName" 
                      HorizontalAlignment="Left" Margin="162,96,0,0" VerticalAlignment="Top" Width="120"/>
            <TextBlock Text="{Binding SelectedGenre.GenreName}" HorizontalAlignment="Left" Margin="152,210,0,0" TextWrapping="Wrap" VerticalAlignment="Top"/>
        </Grid>
    </Window>





    Koopakiller [kuːpakɪllɐ] (Tom Lambert)
    Webseite | Code Beispiele | Facebook | Twitter | Snippets   C# ↔ VB.NET Konverter
    Markiert bitte beantwortende Posts als Antwort und bewertet Beiträge. Danke.

    Mittwoch, 4. Dezember 2013 18:57
    Moderator
  • Hi....superschnelle Antwort,

    vielen Dank ersteinmal. Ist wohl weitestgehend, wie du das geschrieben hast.

    public class Genre

    Public string Desceiption { get; set; }

    -----------------------------------------------------

    public class Control : INotifyPropertyChanged

    Public string Genre (mit INotify.....)

    public List<Genre> TmpGenreList (ebenfalls mit INotify)

    ------------------------------------------------------

    Combobox Items werden angezeigt. Ich habe mir das schon gedacht, dass ein Selected Item mir nicht tatsächlich den Wert liefert. Ich probier derweil deine Vorschläge aus.

    xmlns:local="clr-namespace:WpfApplication3" >
    <Window.Resources>
       <local:Control x:Key="Con" />
    </Window.Resources>
    
    <StackPanel>
      <TextBlock Text="{Binding Source={StaticResource Con}, 
                 Path=Genre, 
                 Mode=OneWay}"/>
    
    <ComboBox x:Name="cmbBoxGenre" 
              ItemsSource="{Binding}" 
              DisplayMemberPath="Description" 
              SelectedItem="{Binding  Source=StaticResource Con}, 
              Path=Genre, 
              Mode=OneWayToSource}" />
    
            <Button Content="Load" Click="Button_Click" /> (Füllt die Liste von einer Datenbank)
        </StackPanel>
    </Window>


    Mittwoch, 4. Dezember 2013 19:35
  • Ach, vielleicht sollte ich noch anmerken, dass ich das eben über den Umweg der Propperties machen möchte. Keine grosse Geschichte. Nur zum Üben und so. Ich will halt ein wenig in MVVM durchsteigen und muss ja erstmal Binding lernen. Na ja, später dann halt noch Commands.

    Es ist nichts Heiliges. Aber auch nicht verkehrt, es zu wissen.

    Mittwoch, 4. Dezember 2013 19:42
  • Ich habe in meinem Beispiel das selektierte Item an eine EIgenschaft im Codebehind gebunden und dann den TextBlock auch an diese Eigenschaft.

    Es ist allerdings auch kein Problem den TextBlock direkt an die ComboBox zu binden:

    Text="{Binding SelectedItem.GenreName, ElementName=comboBox1}"


    Koopakiller [kuːpakɪllɐ] (Tom Lambert)
    Webseite | Code Beispiele | Facebook | Twitter | Snippets   C# ↔ VB.NET Konverter
    Markiert bitte beantwortende Posts als Antwort und bewertet Beiträge. Danke.

    Mittwoch, 4. Dezember 2013 19:50
    Moderator
  • Hmmmm.........,

    das habe ich ja auch so gemacht. Ich weiss aber noch nicht so recht, wie ich anstatt "WpfApplication3.Genre" das selektierte Item angezeigt bekomme. Jetzt habe ich das mit nem event versucht.....geht auch nicht. Da glaubt man, dass man wenigstens sowas hinbekommt und dann muss man feststellen, dass man zu blöd ist.

    SelectionChanged="".......in der Behind=

    string genre = cmBoxGenre.SelectedValue.ToString();

    control.Genre = genre;

    mit dem Debugger durchgegangen und in der Property steht jetzt zwar endlich das richtige, aber der TextBlock zeigt jetzt gar nichts an.......hääää(obwohl INotyfiy implentiert is).

    Bin doch soooo kurz vorm Ziel.....was fehlt noch? Ihr Weisen aller Weisen, ein Rat würde mir jetzt weiter helfen.

    Mittwoch, 4. Dezember 2013 20:54
  • Naja, wenn du alles so gemacht hast wie ich in meinem ersten Post, dann sollte es auch funktionieren.

    Beim TextBlock binde ich an SelectedGenre.GenreName. SelectedGenre ist dabei meine Eigenschaft im Codebehind. GenreName ist die Eigenschaft im Genre-Objekt.

    Das der Wert der Eigenschaft nicht im Fenster angezeigt wird, kann viele Ursachen haben. Unter anderem ist die Eigenschaft vielleicht nicht public oder es liegt ein Tippfehler beim aulösen von INorifyPropertyChanged vor. usw...

    Wenn du willst, kannst du dein Projekt mal auf SkyDrive hochladen, damit ich mal drüber gucke, warum es nicht geht.
    Kurzanleitung zu SkyDrive
    Gehe dazu auf http://skydrive.com/, melde dich an und ziehe die als ZIP-Datei verpackte Projektmappe auf die weiße Fläche. (Zum Verpacken: Rechtsklick auf den Projektordner > Senden an > ZIP-komprimierter Ordner)
    Danach kannst du einen Rechtsklick auf die hoch geladene Datei machen und "Teilen" wählen und einen Link abrufen, den du dann hier postest.


    Koopakiller [kuːpakɪllɐ] (Tom Lambert)
    Webseite | Code Beispiele | Facebook | Twitter | Snippets   C# ↔ VB.NET Konverter
    Markiert bitte beantwortende Posts als Antwort und bewertet Beiträge. Danke.

    Mittwoch, 4. Dezember 2013 21:06
    Moderator
  • Hi....,

    herzlichen Dank für deine Antworten. Ich habe etwas nicht gewusst........"SelectedValuePath"

    <TextBlock Text="{Binding Source={StaticResource Con},
                Path=Genre, (Property in Klasse Control)
                Mode=OneWay}"/>

    <ComboBox x:Name="cmbBoxGenre" ItemsSource="{Binding}" DisplayMemberPath="Description" SelectedValuePath="Description" SelectedValue="{Binding Source={StaticResource Con}, Path=Genre, (Property in Classe Control) Mode=OneWayToSource}" />

    <Button Content="Load" Click="Button_Click" /> (this.cmmBoxGenre.DataSource =

    control.LoadGenre(conDB);

    nochmal recht herzlichen Dank für deine Mühe. Hab schon einige Male Fragen gepostet und immer wieder aufschlussreiche Antworten bekommen. Ne coole Sache hier......


    Mittwoch, 4. Dezember 2013 21:30
  • Hmmmm......falls du Lust auf Verbesserungsvorschläge hast. Ist noch alles ein wenig verspult. Na ja, bin ja noch am lernen.

    https://skydrive.live.com/redir?resid=7AA862DAEDDEA0CA!340&authkey=!ANZWUFGJBp9v8HY&ithint=file%2c.zip

    hoffe, dass der Link funktioniert.

    Mittwoch, 4. Dezember 2013 21:47
  • Hallo,
    schön wenn es jetzt läuft :)

    Bei einer ComboBox ist das so natürlich möglich. Ich würde dir zum lernen empfehlen dir meinen anfangs geposteten Code trotzdem nochmal anzuschauen, damit es später mal leichter ist das Problem zu lösen. Denn bei MVVM wird dir das sicherlich noch häufiger begegnen ;)

    Zu deinem Projekt:
    Ich habe es zwar nur kurz überflogen, aber wirkliche Probleme sind mir nicht aufgefallen. Für MVVM musst du natürlich noch ein Wneig die einzelnen Schichten von einander trennen, aber sonst scheint es ok zu sein.

    PS: Wenn deine Frage soweit beantwortet ist, dann markiere die hilfreichste(n) Posts als Antwort. Somit können Andere mit dem gleichen Problem schneller eine Lösung finden.


    Koopakiller [kuːpakɪllɐ] (Tom Lambert)
    Webseite | Code Beispiele | Facebook | Twitter | Snippets   C# ↔ VB.NET Konverter
    Markiert bitte beantwortende Posts als Antwort und bewertet Beiträge. Danke.

    Donnerstag, 5. Dezember 2013 16:02
    Moderator
  • Hallo mradic,

    Ich gehe davon aus, dass die Antwort Dir weitergeholfen hat.
    Wenn nicht, neue Rückfragen oder Ergänzungen zu diesem Thread bleiben weiterhin möglich.

    Danke und viele Grüße,
    Ionut


    Ionut Duma, MICROSOFT   Bitte haben Sie Verständnis dafür, dass im Rahmen dieses Forums, welches auf dem Community-PrinzipEntwickler helfen Entwickler“ beruht, kein technischer Support geleistet werden kann oder sonst welche garantierten Maßnahmen seitens Microsoft zugesichert werden können.

    Dienstag, 10. Dezember 2013 12:08
    Moderator