Entwickler-Ecke

C# - Die Sprache - Bug DataGridView - BindingList


maxx - Sa 17.04.10 20:45
Titel: Bug DataGridView - BindingList
Testumgebung:

Win XP
Visual C# 2008 Express Edition

Wann funktioniert das Programm:
- Wenn man mit <DbArtist> arbeitet oder
- wenn man mit <object> arbeitet und this.dbArtistList.FetchIn(); im Form1-Konstruktor aufruft.

Wann funktioniert das Programm nicht:
Wenn man mit <object> arbeitet und this.dbArtistList.FetchIn(); nicht im Form1-Konstruktor aufruft. Im DataGridView wird zwar eine Zeile eingetragen, allerdings sind die Zelleninhalte leer.

Oberfläche:
- DataGridView dataGridView1
- Button btnAddArtist

Programm:


C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Windows.Forms;
namespace WindowsFormsApplication1
{
   public partial class Form1 : Form
   {
      DbArtistList dbArtistList = new DbArtistList(); // für die DGV-Daten
      public Form1()
      {
         InitializeComponent();
         this.dataGridView1.DataSource = dbArtistList.cDbArtist;

         // OK ... funktioniert immer, auch wenn mit <object> gearbeitet wird:
         this.dbArtistList.FetchIn();
      }
      private void Form1_Load(object sender, EventArgs e)
      {
         // Innerhalb von Load NOK:
         //this.dbArtistList.FetchIn();
      }
      private void btnAddArtist_Click(object sender, EventArgs e)
      {
         // Innerhalb des Buttons NOK:
         this.dbArtistList.FetchIn(); // DB-Abfrage
      }
      private void OnArtistsSelected(object dgv)
      {
         //this.dbArtistList.FetchIn(cId); // DB-Abfrage
         this.dbArtistList.FetchIn(); // DB-Abfrage
      }
   }

   public class DbArtist
   {
      public int iId { get; set; }
      public string sName { get; set; }
   }
   public class DbArtistList
   {
      // NOK, wenn Dialog nicht im Konstruktor von Form1 aufgerufen wird:
      public BindingList<object> cDbArtist = new BindingList<object>();

      //OK:
      //public BindingList<DbArtist> cDbArtist = new BindingList<DbArtist>();

      public void FetchIn() //List<int> cId)
      {
         DbArtist dbArtist = new DbArtist();
         dbArtist.iId = 1;
         dbArtist.sName = "a";

         this.cDbArtist.Add(dbArtist);
      }
   }
}


Könnt ihr mir das bestätigen? Ist das ein Bug? Ev. ein bekannter Bug?


Kha - Sa 17.04.10 21:26

Ich rate mal: Das DGV will vor dem ersten Zeichnen wissen, von welchem Typ die Elemente sind. Also muss es entweder eine typisierte Liste oder vor dem Anzeigen schon mindestens ein Element in den Fingern haben.

Aber spricht überhaupt etwas dagegen, eine typisierte Liste einzubinden? Das DGV wird ja meistens doch eher mit homogenen Daten versorgt.


maxx - Sa 17.04.10 21:31

Zitat:
Also muss es entweder eine typisierte Liste oder vor dem Anzeigen schon mindestens ein Element in den Fingern haben.

Richtig. Macht man schon im Konstruktor einen Eintrag in das DataGridView, gibt es keine Probleme mit <object>.


Kha - Sa 17.04.10 21:34

Äh, ja. Auf diesen Beobachtungen von dir habe ich schließlich meine These aufgebaut :gruebel: .


maxx - Sa 17.04.10 21:44

Nur um keine Misverständnisse aufkommen zu lassen. Man kann grunsätzlich auch mit <object> arbeiten:


C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace WindowsFormsApplication1
{
   public partial class Form1 : Form
   {
      DbArtistList dbArtistList = new DbArtistList();
      public Form1()
      {
         InitializeComponent();
      }
      private void button1_Click(object sender, EventArgs e)
      {
         this.dbArtistList.FetchIn();
         this.dataGridView1.DataSource = dbArtistList.cDbArtist;
      }
   }
   public class DbArtist
   {
      public int iId { get; set; }
      public string sName { get; set; }
   }
   public class DbArtistList
   {
      public BindingList<object> cDbArtist = new BindingList<object>();
      public void FetchIn()
      {
         DbArtist dbArtist = new DbArtist();
         dbArtist.iId = 1;
         dbArtist.sName = "a";

         this.cDbArtist.Add(dbArtist);
      }
   }
}

Der Unterschied zum anderen Programm ist, dass die DataSource-Bindung erst NACH der Datenerfassung erfolgt.


-- Moderiert von user profile iconKha: Beiträge zusammengefügt --


Und? Habe ich hier einen Bug entdeckt? Sollte man den melden?


-- Moderiert von user profile iconKha: Beiträge zusammengefügt --


Zitat:
Aber spricht überhaupt etwas dagegen, eine typisierte Liste einzubinden? Das DGV wird ja meistens doch eher mit homogenen Daten versorgt.

List wollte ich nicht verwenden, weil man es erst NACH einer DataSource-Zuweisung verwenden kann. Und <object> wollte ich verwenden, damit man beliebige BindingList´s einer Methode übergeben kann.


Kha - Sa 17.04.10 22:52

Ja, meinte eine BindingList ;) . Kannst du dich bei dem Methoden-Parameter nicht auf IBindingList beschränken?


maxx - Sa 17.04.10 22:59

Herrlich! Wunderbare Lösung für das Problem! Danke :)