none
Combobox mit Datenbindung (wpf) RRS feed

  • Frage

  • Hallo,

    ich habe eine Combobox die soll Steuersätze zur Auswahl anzeigen (tblMwSt)

    xaml

            <ComboBox x:Name="cboMwSt" HorizontalAlignment="Left" Margin="623,104,0,0" VerticalAlignment="Top" Width="142" Height="23" ItemsSource="{Binding lngMwSt}"/>
    

    EIch fülle die Combox überfolgenden Aufruf:

            private void pFillCBO(ComboBox comboBoxName, string strSQL, string strMember, string strValue)
            {
                SqlConnection cn = new SqlConnection(conString);
                SqlCommand cmd = new SqlCommand();
                cmd.Connection = cn;
                cmd.CommandText = strSQL;
                cn.Open();
                DataSet ds = new DataSet();
                SqlDataAdapter adpp = new SqlDataAdapter(cmd);
                adpp.Fill(ds, "tblCBO");
                comboBoxName.ItemsSource = ds.Tables[0].DefaultView;
                comboBoxName.DisplayMemberPath = ds.Tables[0].Columns[strMember].ToString();
                comboBoxName.SelectedValuePath = ds.Tables[0].Columns[strValue].ToString();
            }

    Es sollen beim Anzeigen die im Artikel bereits hinterlegten Steuersätze direkt angezeigt werden.Die Artikel zeige ich wie folgt an:

            private void ViewFill()
            {
                SqlConnection cn = new SqlConnection(conString);
                SqlCommand cmd = new SqlCommand();
                cmd.Connection = cn;
                cmd.Parameters.Add("@Filter", SqlDbType.NChar).Value = cmdParFilter;
                cmd.CommandText = cmdString + " '" + cmdParFilter + "'";
                cn.Open();
                DataSet ds = new DataSet();
                SqlDataAdapter adpp = new SqlDataAdapter(cmd);
                adpp.Fill(ds);
                this.DataContext = ds.Tables[0];
                view = (BindingListCollectionView)CollectionViewSource.GetDefaultView(this.DataContext);
                cn.Close();
            }

    Mein Problem ist das die im Artikel ausgewählten Steuersätze nicht angezeigt werden.

    Bin Newbie und finde keinen richtigen Ansatz deshalb bitte ich um Hilfe.

    Danke

    Ralf

    Samstag, 28. Mai 2016 10:18

Antworten

  • Hallo Ralf,

    deine Beschreibung klingt für mich so als gibt es ein Problem mit der SQL-Abfrage. Aber die sehen wir nicht.

    Folgendes wirkt etwas seltsam:

    cmd.Parameters.Add("@Filter", SqlDbType.NChar).Value = cmdParFilter;
    cmd.CommandText = cmdString + " '" + cmdParFilter + "'";

    Wenn du einen Parameter hinzufügst, dann musst du im SQL den Namen des Parameters nutzen und nicht den Parameter wieder im Klartext in das SQL einbauen. Die 2. Zeile müsste daher vermutlich so aussehen:

    cmd.CommandText = cmdString + " @Filter";

    Oder aber du setzt das @Filter direkt in cmdString ein.

    Deiner Beschreibung nach hätte ich es so verstanden das du je nachdem welcher Artikel ausgewählt wurde, du die verschiedenen Steuersätze in einer ComboBox anzeigen willst. Jedoch sehe ich in pFillCBO keinen Code der die Ergebnis-Auflistung irgendwie ausfiltert.
    Wenn du dagegen die Artikel anzeige abhängig von der Steuerauswahl in der Mehrwertsteuer-CcomboBox machen willst, dann wird wohl cmdParFilter den Steuersatz enthalten. Wird dieser Auch richtig zugewiesen?

    Wenn ich ein Textfeld daneben setze dann sehe ich aber den korrekten Wert aus der Tabelle.

    Vermutlich meinst du einen TextBlock oder ein label. So oder so können die aber immer nur einen Wert anzeigen. Das andere müssten dagegen Listen sein.

    PS: Du solltest für die Verbindung usw. using-Blöcke nutzen um sie in jedem Fall wieder ordentlich zu schließen. Sonst bekommst du früher oder später Probleme. Siehe auch: Uses of “using” in C# und What is the C# Using block and why should I use it? [duplicate]


    Tom Lambert - .NET (C#) MVP
    Wozu Antworten markieren und für Beiträge abstimmen? Klicke hier.
    Nützliche Links: .NET Quellcode | C# ↔ VB.NET Konverter | Account bestätigen (Verify Your Account)
    Ich: Webseite | Code Beispiele | Facebook | Twitter | Snippets

    Samstag, 28. Mai 2016 16:51
    Moderator
  • Hi Ralf,
    mir ist aus Deinen Schilderungen unklar, wie das Datenbankmodell aussieht, wenn - wie Du schreibst - ein Artikel Mehrwertsteuersätze (mehrere) haben kann. So etwas ist nicht üblich, und, falls doch, ist es über eine Verbindungstabelle zwischen den Artikeln und den zulässigen Mehrwertsteuersätzen zu lösen.

    Üblich ist, dass ein Artikel genau einen Mehrwertsteuersatz hat. In diesem Fall kann es zwei Tabellen geben: Artikel und zulässige Mehrwertsteuersätze. Jeder Artikelsatz verweist dann auf den konkreten Mehrwertsteuersatz (Master-Child, wobei Child der Artikel und Master als Nachschlagewert der Mehrwertsteuersatz ist).

    Prinzipiell würde ich an eine solche Lösung folgendermaßen herangehen:

    1. Anstelle untypisierter Objekte (DataTable usw.) würde ich mindestens typisierte DataSets nutzen, besser noch das Entity Framework.

    2. Für die Anzeige der Artikel würde ich eine Sicht nutzen, die beim Wechsel des aktuellen Datensatzes ein Ereignis auslöst, mit dem man die Anzeige des Mehrwertsteuersatzes aktualisieren kann.

    3. Weiterhin würde ich diese Geschäftslogik richtig kapseln, damit sie unabhängig von der Oberfläche ist und damit automatisch getestet werden kann.


    --
    Viele Grüsse
    Peter Fleischer (MVP, Partner)
    Meine Homepage mit Tipps und Tricks
    Kommas richtig setzen!
    Schüler sagen, Lehrer haben es gut.
    Schüler, sagen Lehrer, haben es gut

    Sonntag, 29. Mai 2016 08:41

Alle Antworten

  • Hallo Ralf,

    was genau meinst du mit "nicht angezeigt"? Vorausgesetzt dein Query gibt auch Daten zurück, fällt mir nur auf, dass deine ComboBox im XAML cboMwSt heißt, im C# sprichst du aber ein comboBoxName an.

    • Die Zuweisung von DisplayMemberPath und SelectedValuePath machst du aber auch recht umständlich. Die Variablen strMember und strValue enthalten vermutlich die Namen der Spalten, diese kannst du auch direkt den Eigenschaften zuweisen. Denn durch den Aufruf von ToString erhältst du auch nur den Spaltennamen.

    Tom Lambert - .NET (C#) MVP
    Wozu Antworten markieren und für Beiträge abstimmen? Klicke hier.
    Nützliche Links: .NET Quellcode | C# ↔ VB.NET Konverter | Account bestätigen (Verify Your Account)
    Ich: Webseite | Code Beispiele | Facebook | Twitter | Snippets

    Samstag, 28. Mai 2016 13:55
    Moderator
  • Hallo Tom,

    es werden in der Combobox die Werte angezeigt jedoch nicht die Werte die beim Artikel in der Datenbank enthalten sind.

    Wenn ich ein Textfeld daneben setze dann sehe ich aber den korrekten Wert aus der Tabelle. Es scheint also ein Problem zwischen dem Wert aus der Tabelle Artikel und der Tabelle MwSt zu geben.

    Ich hab die pFillCBO um mehrere Comboboxen füllen zu können.

    Danke

    Ralf

    Samstag, 28. Mai 2016 15:08
  • Hallo Ralf,

    deine Beschreibung klingt für mich so als gibt es ein Problem mit der SQL-Abfrage. Aber die sehen wir nicht.

    Folgendes wirkt etwas seltsam:

    cmd.Parameters.Add("@Filter", SqlDbType.NChar).Value = cmdParFilter;
    cmd.CommandText = cmdString + " '" + cmdParFilter + "'";

    Wenn du einen Parameter hinzufügst, dann musst du im SQL den Namen des Parameters nutzen und nicht den Parameter wieder im Klartext in das SQL einbauen. Die 2. Zeile müsste daher vermutlich so aussehen:

    cmd.CommandText = cmdString + " @Filter";

    Oder aber du setzt das @Filter direkt in cmdString ein.

    Deiner Beschreibung nach hätte ich es so verstanden das du je nachdem welcher Artikel ausgewählt wurde, du die verschiedenen Steuersätze in einer ComboBox anzeigen willst. Jedoch sehe ich in pFillCBO keinen Code der die Ergebnis-Auflistung irgendwie ausfiltert.
    Wenn du dagegen die Artikel anzeige abhängig von der Steuerauswahl in der Mehrwertsteuer-CcomboBox machen willst, dann wird wohl cmdParFilter den Steuersatz enthalten. Wird dieser Auch richtig zugewiesen?

    Wenn ich ein Textfeld daneben setze dann sehe ich aber den korrekten Wert aus der Tabelle.

    Vermutlich meinst du einen TextBlock oder ein label. So oder so können die aber immer nur einen Wert anzeigen. Das andere müssten dagegen Listen sein.

    PS: Du solltest für die Verbindung usw. using-Blöcke nutzen um sie in jedem Fall wieder ordentlich zu schließen. Sonst bekommst du früher oder später Probleme. Siehe auch: Uses of “using” in C# und What is the C# Using block and why should I use it? [duplicate]


    Tom Lambert - .NET (C#) MVP
    Wozu Antworten markieren und für Beiträge abstimmen? Klicke hier.
    Nützliche Links: .NET Quellcode | C# ↔ VB.NET Konverter | Account bestätigen (Verify Your Account)
    Ich: Webseite | Code Beispiele | Facebook | Twitter | Snippets

    Samstag, 28. Mai 2016 16:51
    Moderator
  • Hallo Tom,

    danke für die Infos.

    Habe mich wohl nicht verständlich ausgedrückt.

    Ich möchte bei allen Artikeln in der Combobox alle Steuersätze anzeigen lassen aus der Tabelle MwSt (Die werden auch angezeigt). Beim Wechsel der Datensätze sollen aber beim Artikel hinterlegten Steuersätze angezeigt werden.

    <ComboBox x:Name="cboMwSt" HorizontalAlignment="Left" Margin="623,104,0,0" VerticalAlignment="Top" Width="142" Height="23" ItemsSource="{Binding lngMwSt}"/>

    Ich lese die Artikel wie folgt aus (In der Tabelle ist das Feld MwSt - lngMwSt):

                StringBuilder sb = new StringBuilder();
                sb.AppendLine("EXEC qryStammArtikel");
                SqlConnection cn = new SqlConnection(conString);
                SqlCommand cmd = new SqlCommand();
                cmd.Connection = cn;
                cmd.CommandText = sb.ToString();
                cn.Open();
                DataSet ds = new DataSet();
                SqlDataAdapter adpp = new SqlDataAdapter(cmd);
                adpp.Fill(ds);
                this.DataContext = ds.Tables[0];
                view = (BindingListCollectionView)CollectionViewSource.GetDefaultView(this.DataContext);
                cn.Close();

    und fülle die Combobox mit

                SqlConnection cn = new SqlConnection(conString);
                SqlCommand cmd = new SqlCommand();
                cmd.Connection = cn;
                cmd.CommandText = "EXEC qryCBOMwSt";
                cn.Open();
                DataSet ds = new DataSet();
                SqlDataAdapter adpp = new SqlDataAdapter(cmd);
                adpp.Fill(ds, "tblCBO");
                comboBoxName.ItemsSource = ds.Tables[0].DefaultView;
                comboBoxName.DisplayMemberPath = ds.Tables[0].Columns["decSatz"].ToString();
                comboBoxName.SelectedValuePath = ds.Tables[0].Columns["cntNr"].ToString();

    Im Moment sehe ich aber nur Werte in der Combobox und nicht direkt den Wert der in der Artikeldatenbank hinterlegt ist.

    Hoffe ich hab es jetzt besser beschrieben.

    Danke

    Ralf


    Samstag, 28. Mai 2016 21:11
  • Hallo Tom,

    ein Verständnisfrage zu deinem PS.

    Ich dachte das ich es durch

    cn.Close();

    Schließe und wieder Freigebe.

    Ich habe jetzt mal wie folgt umgestellt

                using (SqlConnection cn = new SqlConnection(conString))
                {
                    SqlCommand cmd = new SqlCommand();
                    cmd.Connection = cn;
                    cmd.CommandText = "EXEC qryStammArtikel";
                    cn.Open();
                    DataSet ds = new DataSet();
                    using (SqlDataAdapter adpp = new SqlDataAdapter(cmd))
                    {
                        adpp.Fill(ds);
                        this.DataContext = ds.Tables[0];
                        view = (BindingListCollectionView)CollectionViewSource.GetDefaultView(this.DataContext);
                    }
                }

    So wäre also die richtige Variante?
    DANKE
    Ralf

    Samstag, 28. Mai 2016 21:24
  • Hi Ralf,
    mir ist aus Deinen Schilderungen unklar, wie das Datenbankmodell aussieht, wenn - wie Du schreibst - ein Artikel Mehrwertsteuersätze (mehrere) haben kann. So etwas ist nicht üblich, und, falls doch, ist es über eine Verbindungstabelle zwischen den Artikeln und den zulässigen Mehrwertsteuersätzen zu lösen.

    Üblich ist, dass ein Artikel genau einen Mehrwertsteuersatz hat. In diesem Fall kann es zwei Tabellen geben: Artikel und zulässige Mehrwertsteuersätze. Jeder Artikelsatz verweist dann auf den konkreten Mehrwertsteuersatz (Master-Child, wobei Child der Artikel und Master als Nachschlagewert der Mehrwertsteuersatz ist).

    Prinzipiell würde ich an eine solche Lösung folgendermaßen herangehen:

    1. Anstelle untypisierter Objekte (DataTable usw.) würde ich mindestens typisierte DataSets nutzen, besser noch das Entity Framework.

    2. Für die Anzeige der Artikel würde ich eine Sicht nutzen, die beim Wechsel des aktuellen Datensatzes ein Ereignis auslöst, mit dem man die Anzeige des Mehrwertsteuersatzes aktualisieren kann.

    3. Weiterhin würde ich diese Geschäftslogik richtig kapseln, damit sie unabhängig von der Oberfläche ist und damit automatisch getestet werden kann.


    --
    Viele Grüsse
    Peter Fleischer (MVP, Partner)
    Meine Homepage mit Tipps und Tricks
    Kommas richtig setzen!
    Schüler sagen, Lehrer haben es gut.
    Schüler, sagen Lehrer, haben es gut

    Sonntag, 29. Mai 2016 08:41
  • Hallo,

    danke für eure Hinweise!

    Viele Grüße

    Ralf


    • Bearbeitet Joe72ka Sonntag, 29. Mai 2016 11:57
    Sonntag, 29. Mai 2016 09:36
  • Hallo Peter,

    eine Frage hab ich noch zu zum Entity Framework.

    Ich finde kein richtiges Beispiel, das lauffähig ist. In den meisten wird einfach erwähnt das nach dem Einbinden die Tabellen im Data Sources vorhanden sind. Das ist bei mir nicht der Fall.

    Auch finde ich kein Beispiel wie ich dann Parameter übergebe um Daten zu Filtern.

    Hast du eine Quelle?

    Danke

    Sonntag, 29. Mai 2016 22:23
  • Hi Ralf,
    die Anwendung des EF ist recht einfach; es macht aber recht viel im Hintergrund.

    Hauptkomponenten im Programm sind der Context und Deine Datenstrukturen in Form von Datenklassen.

    Vereinfacht kann man die Arbeit mit dem EF so darstellen. Zur Arbeit ist eine Instanz des Context erforderlich, die den clientseitigen Cursor verwaltet. Typischerweise wird mittels LinQ eine Abfrage der benötigten Daten deklariert. Erst wenn die Abfrage (LinQ) ausgeführt wird, werden die Daten geholt und dem Anfordernden bereitgestellt. Das kann beispielsweise auch über eine Persistierung der Daten mittels ToList oder ToArray erreicht werden. Die Datenobjekte selbst liegen nach dem Laden in einem Puffer im Hintergrund, auf den auch ober die Local-Eigenschaft zugegriffen werden kann. Zu jedem Datenobjekt wird der Zustand mitgeführt, so dass ein entsprechendes Rückspeichern der Änderungen (neu, geändert, gelöscht) möglich wird.

    Meist ist der Umfang der Daten in der Datenbank recht groß und nur ein kleiner Teil der Daten wird im Programm benötigt. Das wird realisiert, indem in der Abfrage (LinQ) über where die Anzahl der abgerufenen Daten eingeschränkt (gefiltert) wird.


    --
    Viele Grüsse
    Peter Fleischer (MVP, Partner)
    Meine Homepage mit Tipps und Tricks
    Kommas richtig setzen!
    Schüler sagen, Lehrer haben es gut.
    Schüler, sagen Lehrer, haben es gut

    Montag, 30. Mai 2016 09:52
  • Hi Peter,

    wieso hat sich den ET bisher nicht so richtig durchgesetzt?

    Grüße

    Ralf

    Dienstag, 31. Mai 2016 11:39
  • Hi Ralf,
    woher nimmst Du diese Erkenntnis?

    Ich kann nicht nachvollziehen, dass sich das EF (vermutlich meinst Du das mit ET) nicht durchgesetzt hat. Jede Technologie hat Vor- und Nachteile. Je komplexer eine Technologie ist, desto schwieriger kann es sein, sie bei speziellen Anforderungen effektiv anzuwenden. Eine effektive Nutzung setzt umfangreiche Kenntnisse voraus, die bei einfach handhabbaren Technologien oft nicht ausreichend vorhanden sind. Ein einfach verständliches Beispiel kann die unpassende Persistierung von LinQ-Abfragen sein, die zu ungerechtfertigt hohem Ressourcenverbrauch führen kann.


    --
    Viele Grüsse
    Peter Fleischer (MVP, Partner)
    Meine Homepage mit Tipps und Tricks
    Kommas richtig setzen!
    Schüler sagen, Lehrer haben es gut.
    Schüler, sagen Lehrer, haben es gut

    Dienstag, 31. Mai 2016 12:04
  • Hi Peter,

    ja Sorry meinte EF, ich hab viele Literatur zur Datenbankanbindung gefunden und die wenigsten gehen auf EF ein und wenn nur sehr beiläufig.

    In einem Buch stand "In der Praxis hat sich das Entity Framework aber bisher noch nicht so weit durchgesetzt, dass dessen Bevorzugung in diesem Beispiel gerechtfertigt wäre." Das ist zwar von 2012 aber auch danach finde ich kaum Ansätze in Büchern. Das war der Grund warum ich die oben beschriebene Technologie verwendet habe.

    Viele Grüße

    Ralf

    Dienstag, 31. Mai 2016 12:51
  • Hi Ralf,
    4 Jahre sind bei den Innovationszyklen in der Rechentechnik Welten. Die MSDN ist voll mit Beispielen zur Nutzung des EF. Wegen der Einfachkeit der Nutzung des EF werden die Beispiel vermutlich schnell übersehen oder nicht erkannt.

     

    --
    Viele Grüsse
    Peter Fleischer (MVP, Partner)
    Meine Homepage mit Tipps und Tricks
    Kommas richtig setzen!
    Schüler sagen, Lehrer haben es gut.
    Schüler, sagen Lehrer, haben es gut

    Dienstag, 31. Mai 2016 13:25