none
DataGridView datengebunden aktualisiert nicht nach Sortierung RRS feed

  • Frage

  • Hallo, nun wäre ich auch mal recht dankbar für ein paar Ideen. Komme hier einfach nicht weiter...

    Es geht um ein DataGridView, datengebunden. Nach der Anbindung an eine DataTable kann eine zusätzliche Spalte eingefügt werden, um die Reihenfolge der Zeilen zu ändern (zum einfügen von Zeilen oder zum verschieben von Zeilen). Hab das so weit hinbekommen, nur nach dem Umnummerieren der Zeilen wird das DGV nicht aktualisiert. Wenn ich ein wenig in dem Grid herumklicke, dann wird die Sortierung jedoch irgendwann nachgeholt. Irgendwie komischer Effekt.

    Wäre für jeden Hinweis auf den Übeltäter dankbar!

    Gruß Martin

     

     

     

    Freitag, 19. August 2011 16:39

Alle Antworten

  • Vielleicht noch als Zusatzinfo, ich hab da schon eine Menge rumprobiert.

    EndEdit und Refresh haben keine Wirkung.

    Wenn ich auf den Spaltenheader der Indexspalte klicke, dann wird auch nicht immer richtig sortiert. Mal ein Beispiel:

    Ich hab Zwei Zeilen A und B. Dann fülle ich die Indexspalte. Das Ergebnis ist

    0 A

    1 B

    Nun wird eine Zeile in der DataTable nach "A" eingefügt. Angezeigt wird nun

    2 B

    0 A

    1 C

    Die Zuordnung der Indizes zu den Zeilen stimmt, aber die Reihenfolge nicht. Ganz verrückt wirds, wenn ich jetzt auf den Spaltenheader klicke, um die Sortierreihenfolge zu ändern. Dann bekomme ich:

    1 C

    0 A

    2 B

    Wenn ich dann ein wenig herumklicke in dem Grid, dann erscheint plötzlich die richtige Reihenfolge

    0 A

    1 C

    2 B

    Freitag, 19. August 2011 18:58
  • Hallo F.,

    das kann an mehreren Sachen liegen, ein Beispiel-Projekt würde da sicher hilfreich sein, weil Dein "Umnummerieren" vom Code unklar ist und wie Du die Spalte einfügst etc.. Ggf. nutze dafür https://skydrive.live.com/, damit es alle einsehen können.

     

     


    ciao Frank
    Freitag, 19. August 2011 19:28
  • Hallo F.,

    dennoch hier einmal ein Beispiel, wo die Sortierung richtig funktioniert, wenn eine Spalte zugefügt wird, aber es gibt eben viele Szenarien, die gemeint sein können.
    [Szenario: Spalte an DataSource anfügen]:

    using System;
    using System.ComponentModel;
    using System.Data;
    using System.Windows.Forms;
    
    namespace WinDgvColumnSorting
    {
     public partial class Form1 : Form
     {
      Button btnSpalteZufügen = new Button();
      DataGridView dgv = new DataGridView();
      FlowLayoutPanel flp = new FlowLayoutPanel();
    
      public Form1()
      {
       InitializeComponent();
       flp.Dock = DockStyle.Fill;
       btnSpalteZufügen.Text = "Spalte zufügen";
       btnSpalteZufügen.AutoSize = true;
       btnSpalteZufügen.Click += SpalteZufügen_Click;
       flp.Controls.Add(btnSpalteZufügen);
       dgv.Width = 400; Width = 500;
       flp.Controls.Add(dgv);
       Controls.Add(flp);
      }
    
      void SpalteZufügen_Click(object sender, EventArgs e)
      {
       dgv.SuspendLayout();
       Daten.SpalteZufügen("Anzahl Kinder");
       dgv.ResumeLayout();
       btnSpalteZufügen.Enabled = false;
      }
    
      private ListSortDirection Sortierung(SortOrder alteSortOrder)
      {
       switch (alteSortOrder)
       {
        case SortOrder.Ascending: return ListSortDirection.Ascending;
        case SortOrder.Descending: return ListSortDirection.Descending;
        default: return ListSortDirection.Ascending;
       }
      }
    
      private void Form1_Load(object sender, EventArgs e)
      {
       dgv.DataSource = Daten.DemoDatenPersonen();
      }
     }
    
     class Daten
     {
      private static DataTable dt = new DataTable("Person");
      private static BindingSource bs = new BindingSource();
    
      public static BindingSource DemoDatenPersonen()
      {
       dt.Columns.Add("Name");
       dt.Columns.Add("Geburtstag", typeof(DateTime));
       dt.Rows.Add("Schmidt", new DateTime(1980, 1, 1));
       dt.Rows.Add("Meyer", new DateTime(1981, 2, 2));
       dt.Rows.Add("Müller", new DateTime(1982, 3, 3));
       dt.AcceptChanges();
       bs.DataSource = dt;
       return bs;
      }
    
      public static void SpalteZufügen(string spaltenName)
      {
       dt.Columns.Add(spaltenName, typeof(int));
       SpaltenDemodatenFüllen(spaltenName);
      }
    
      private static void SpaltenDemodatenFüllen(string spaltenName)
      {
       DataColumn column = dt.Columns[spaltenName];
       for (int i = 0; i < dt.Rows.Count; i++)
        dt.Rows[i][column] = i;
      }
    
     }
    }
    
    


    ciao Frank
    Samstag, 20. August 2011 10:52
  • Hallo,

    besten Dank für die Hinweise und das Beispiel. Ja das Problem scheint wirklich die Fülle der Möglichkeiten zu sein. Ansonsten bin ich mit C# und .Net ja super zufrieden, aber dieser Fall hat mich echt Nerven gekostet. Aber ich denke ich habs jetzt gefunden.

    Ich hab eine Ableitung von DataGridView gebaut und da schon einige Zusatzfunktionen installiert, die alle gut funktionieren. Das Grid ist grundsätzlich an eine DataTable als DataSource gebunden. Bei Bedarf (z.B. eine Zeile ist ausgewählt und Key Insert wird gedrückt) wird die Indexspalte in der DataTable erzeugt und gefüllt (ähnlich wie in dem Beispiel oben unter "SpaltenDemodatenFüllen"). Aber das mache ich im DefaultView der DataTable und hier gibt es zwei Möglichkeiten:

    1.: for (int i = dataTable.DefaultView.Count - 1; i >= 0; i--) dataTable.DefaultView[i].Row["Indexspalte"] = i;

    2.: for (int i = dataTable.DefaultView.Count - 1; i >= 0; i--) dataTable.DefaultView[i]["Indexspalte"] = i;  // --> Fehler !

    Danach wird nach der Spalte sortiert und nun können Zeilen eingefügt oder verschoben werden.

    Der Knackpunkt ist, dass Möglichkeit 2. nicht funktioniert. Es wird wie beschrieben nicht bzw. nicht korrekt (im DataGridView) sortiert.

    So wie bei 1. programmiert funktioniert es prima und wie gewünscht. Das überrascht mich, ich dachte die beiden Möglichkeiten wären gleichwertig. Oder hab ich da etwas falsch verstanden? Gibt es einen Unterschied zwischen 1. und 2.?

    Wer interessiert ist, dem kann ich gern den ganzen Code zukommen lassen.

    Viele Grüße, Martin

    --> Sorry, die Schrift ist wohl etwas klein geraten, ich weiß leider nicht, wie sich das hier ändern lässt... 


    • Bearbeitet Funky63 Sonntag, 21. August 2011 11:40 Schriftgröße
    Sonntag, 21. August 2011 11:36
  • Hallo Fu.,

    • Du schriebst: "So wie bei 1. programmiert funktioniert es prima und wie gewünscht. Das überrascht mich, ich dachte die beiden Möglichkeiten wären gleichwertig. Oder hab ich da etwas falsch verstanden? Gibt es einen Unterschied zwischen 1. und 2.?"

    ja, ein himmelweiter Unterschied.

    Die Row bezieht sich auf einen Datensatz der Datenquelle (aus der DataRowView heraus) und ruft die angezeigte DataRow ab.

    Der Wert des Indexers der DataRowView bezieht sich aber auf die (gefilterte, oder sortierte) Sicht, was etwas ganz anderes ist.
    Ich habe in meinem Beispiel ja auch die Daten in die Datenquelle eingefügt. Das ist also dann auch das korrekte Vorgehen.

      


    ciao Frank
    Sonntag, 21. August 2011 16:16
  • Ja verstehe, aber die Daten sollten doch identisch sein. DataRowView ist doch eine Kopie der Zeile der Datenquelle.

    Offenbar ist es so, dass Änderungen der View nicht (oder nicht sofort?) in der Quelle abgebildet werden.

    Andererseits zeigt das DataGridView doch das an was in DefaultView der DataSource steht.

    Also es ist doch etwa so: DataSource <-- DefaultView <-- DataGridView

    Und Änderungen im DataGridView werden doch an die DataSource "weitergereicht"!

     

    Montag, 22. August 2011 08:47
  • Hallo Fu.,

    • Du schriebst: "Ja verstehe, aber die Daten sollten doch identisch sein. DataRowView ist doch eine Kopie der Zeile der Datenquelle."

    nein, in der Sicht können Zeilen (oder Spalten) ganz fehlen, weil ein Filter diese z.B. herausnimmt. Dazu kann durch eine Sortierung die Reihenfolge anders sein.

     


    ciao Frank
    Montag, 22. August 2011 12:18
  • Ja sicher, Zeile i in der View ist mit Zeile j in der DataSource verbunden. Und defaultView[i].Row ist diese Zeile j in der DataSource. Diese beiden Zeilen sollten also inhaltlich identisch sein (sofern keine Spalten ausgeblendet sind versteht sich).

    Das muss doch auch der Weg sein, wie Daten aus dem DataGridView an die Source weitergeleitet werden.

    DataGridView Zeile i verweist auf DefaultView Zeile i und diese verweist über .Row auf eine Zeile j in der Source.

    Also sollte es den gleichen Effekt haben, ob ich einen Wert in defaultView[i] oder defaultView[i].Row ändere, weil die Änderung in defaultView[i] sowieso an .Row weitergereicht werden müsste...

    Oder stehe ich jetzt völlig auf dem Schlauch? Lasse mich ja gern überzeugen... :-)))

     

    Montag, 22. August 2011 13:11