2009-04-20 19 views
4

Ich habe ein Problem beim Zuweisen der DataSource Propery auf einem DataGridView Steuerelement. Mein DataSource ist ein DataTable 's DefaultView und, wie erwartet, Spalten werden automatisch in der DataGridView erstellt, um mit denen in der DataTable übereinzustimmen, wenn ich es zuweisen.DataGridView wiederholt Spalten neu erstellen

Was als nächstes passiert ist, dass die Spalten automatisch entfernt und erneut 2 mal durch die DataGridView erstellt werden. Warum würde das passieren?

in einer Form Konstruktor:

//A DataTable is created with 5 columns 
//The DataTable is populated with some rows. 

myDgv.AutoGenerateColumns = true; 
myDgv.DataSource = myDataTable.DefaultView; 
// myDgv.ColumnAdded event is fired 5 times. 
// WHY: myDgv.ColumnRemoved event is fired 5 times. 
// WHY: myDgv.ColumnAdded event is fired 5 times. 
// WHY: myDgv.ColumnRemoved event is fired 5 times. 
// WHY: myDgv.ColumnAdded event is fired 5 times. 

Edit: Hinzugefügt ein (hoffentlich) selbst Beispiel enthalten sind. Wenn ich Breakpoints in den Event-Handlern setze, drücke ich sechs Mal auf "Hinzugefügt" und einmal vier Mal auf "Entfernt". Die DataTable enthält 2 Spalten und ich fordere nie, dass Spalten in meinem Code entfernt werden.

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 asdasdgf 
{ 
    public class Form1 : Form 
    { 
     public Form1() 
     { 
      InitializeComponent(); 

      DataTable dt = new DataTable(); 
      dt.Columns.Add("Col1", typeof(int)); 
      dt.Columns.Add("Col2", typeof(string)); 

      foreach (int i in Enumerable.Range(0, 10)) 
      { 
       var row = dt.NewRow(); 
       row["Col1"] = i; 
       row["Col2"] = "stackoverflow"; 
       dt.Rows.Add(row); 
      } 

      dataGridView1.ColumnAdded += new DataGridViewColumnEventHandler(dataGridView1_ColumnAdded); 
      dataGridView1.ColumnRemoved += new DataGridViewColumnEventHandler(dataGridView1_ColumnRemoved); 

      dataGridView1.DataSource = dt.DefaultView; 
     } 

     void dataGridView1_ColumnRemoved(object sender, DataGridViewColumnEventArgs e) 
     { 
      // Break here 
     } 

     void dataGridView1_ColumnAdded(object sender, DataGridViewColumnEventArgs e) 
     { 
      // Break here 
     } 

     // Form1.Designer.cs contents: 
     #region Windows Form Designer generated code 
     private System.ComponentModel.IContainer components = null; 
     private System.Windows.Forms.DataGridView dataGridView1; 

     protected override void Dispose(bool disposing) 
     { 
      if (disposing && (components != null)) 
      { 
       components.Dispose(); 
      } 
      base.Dispose(disposing); 
     } 



     /// <summary> 
     /// Required method for Designer support - do not modify 
     /// the contents of this method with the code editor. 
     /// </summary> 
     private void InitializeComponent() 
     { 
      this.dataGridView1 = new System.Windows.Forms.DataGridView(); 
      ((System.ComponentModel.ISupportInitialize)(this.dataGridView1)).BeginInit(); 
      this.SuspendLayout(); 
      // 
      // dataGridView1 
      // 
      this.dataGridView1.ColumnHeadersHeightSizeMode = System.Windows.Forms.DataGridViewColumnHeadersHeightSizeMode.AutoSize; 
      this.dataGridView1.Location = new System.Drawing.Point(12, 41); 
      this.dataGridView1.Name = "dataGridView1"; 
      this.dataGridView1.Size = new System.Drawing.Size(240, 150); 
      this.dataGridView1.TabIndex = 0; 
      // 
      // Form1 
      // 
      this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); 
      this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; 
      this.ClientSize = new System.Drawing.Size(284, 264); 
      this.Controls.Add(this.dataGridView1); 
      this.Name = "Form1"; 
      this.Text = "Form1"; 
      ((System.ComponentModel.ISupportInitialize)(this.dataGridView1)).EndInit(); 
      this.ResumeLayout(false); 

     } 

     #endregion 
    } 
} 
+1

Was passiert, wenn Sie stattdessen eine BindingSource verwenden? –

+0

Dasselbe passiert :-( – xyz

+0

Ich habe ein (hoffentlich) eigenständiges Beispiel hinzugefügt. Wenn ich Haltepunkte in den Event-Handlern setze, drücke ich 6 Mal auf 'Added' und 4 Mal auf 'Removed'. Die DataTable enthält 2 Spalten und ich bitte nie um irgendwelche Spalten in meinem Code entfernt zu werden – xyz

Antwort

1

Nach viel Hantieren scheint dies der richtige Weg zu sein.

In Ihrer Load Ereignisbehandlungsform:

dgv.AutoGenerateColumns = false; 
dgv.DataSource = myDataSource; 

In Ihrer Shown Ereignisbehandlungsform:

dgv.AutoGenerateColumns = true; 

das gewünschte Ergebnis des ColumnAdded Ereignisses gibt für jede Spalte abgefeuert einmal werden und die ColumnRemoved Event wird überhaupt nicht gefeuert. (Wenn AutoGenerateColumns = true im Load Event-Handler gesetzt ist, wird es diesen lästigen Add-Remove-Add-Tanz machen.)

1

Wenn myDgv.DataSource alreadys auf etwas festgelegt ist, dass zumindest ein Teil der Hinzufügen/Entfernen Aktionen erklären würde. Dito für wenn die Spalten bereits vorhanden sind Design-Zeit.

Stellen Sie sicher, dass das Raster leer ist und die DataSource-Eigenschaft im Designer gelöscht wird.

Zusätzlich:

lief ich den Code Probe und kann bestätigen, aber man kann (halve), um den Wahnsinn reduzieren, indem Sie den Code aus dem Konstruktor zu einem normalen Ereignis Form_Load zu bewegen. Das ist sowieso der richtige Weg, ich sehe viel zu viele Leute, die den ctor und Load verwechseln.

Aber dann gibt es noch 2 Add und 1 Remove-Aktionen pro Spalte, ich fürchte, wir müssen das zu einigen DataGrid Ineffizienz abonnieren. (Irgendwo in der DataSource.set())

Weitere 2:

Anscheinend ist der Autogeneratecolumns gilt standardmäßig aktiviert und ist nicht direkt einstellbar von Eigenschaftenfenster. Ich habe es gelöscht, indem ich zur Entwurfszeit eine Datenquelle gesetzt (und später gelöscht) habe. Und dann, mit einer gelöschten AutoGenerateColumns-Eigenschaft, liefert nur die zwei Add-Ereignisse.

+0

Das sind beide der Fall, soweit mir bekannt ist.Bitte versuchen Sie den Code, den ich gepostet habe, wenn Sie Zeit haben :-) – xyz

+0

Vielen Dank für Ihre Hilfe . Ich verstehe deinen zweiten Zusatz nicht. Also, standardmäßig .AutoGenerateColumns ist 'true' und .DataSource ist 'null' - sind das nicht die Werte, die ich als Startpunkt begehre? Was bewirkt das Setzen von AGC auf True (wenn es bereits wahr ist) und das manuelle Hinzufügen/Entfernen einer DataSource im Designer? – xyz

+0

Ah, ich habe es in der Reihenfolge erledigt: AGC = false, DataSource zuweisen, AGC = true :-) – xyz

2

Ich habe eine App, die eine Datagridview verwendet den Inhalt einer Datentabelle angezeigt werden, aber ich verknüpfen sie wie folgt aus:

dataGridView.DataSource = dataTable; 

Können Sie das versuchen?

EDIT:

Ich habe auch die folgenden in der Auto-Code generiert:

this.dataGridView.EditMode = System.Windows.Forms.DataGridViewEditMode.EditProgrammatically; 

nicht sicher, warum dies allerdings einen Unterschied machen würde.

+0

Das Gleiche passiert. Entweder mache ich etwas grundsätzlich falsch, oder hier passiert etwas Seltsames - es gibt kaum einen Code in dem Beispiel in der Frage und es passiert immer noch – xyz

1

Vor ein paar Monaten bei der Arbeit haben wir ein Grid-Steuerelement erstellt, das Filterfunktionen (ähnlich wie Excel) eingebaut hat. Anfangs haben wir einen DataGrid-View verwendet und darauf gebaut. Dieses Problem, das Sie jetzt ansprechen, war der größte Dorn in unserer Seite! Da wir ein DGV darunter verwendeten und uns in seine Ereignisse einklinkten, um verschiedene Dinge auszulösen, die wir tun mussten, war das ein absoluter Albtraum. Die DGV ist eine gute Kontrolle, aber unter der Decke tut es etwas wonky sh ** !! Der beste Workaround am Ende des Tages war, die Spalten selbst zu generieren. Ja, es war ein Schmerz, aber zumindest hatten wir die volle Kontrolle.

In unserer endgültigen Version, am Ende kratzten wir alle zusammen, und ging mit der Vererbungsroute. Wir haben von der DGV geerbt und es hat unser Leben viel einfacher gemacht. Nun, ich bin mir nicht sicher, was Sie hier erreichen wollen, aber wenn Sie Ihr eigenes Gitter erstellen, versuchen Sie zuerst die Vererbung! Was die Antwort auf deine Frage betrifft, machst du nichts falsch. Die Datagridview ist einfach so verrückt. Wenn Sie kein Steuerelement für den DGV erstellen und nur diese Ereignisse benötigen, versuche ich, Abstand von der Spalte "hinzugefügt/entfernt" zu halten. Sehen Sie, ob Sie statt dessen bindingcompleted verwenden können.

+0

Danke für den Rat. Ich denke, es wurde zur Arbeit überredet (siehe oben), aber ich denke, es kann ein bisschen drunter und drüber sein! – xyz

1

Ich habe eine Lösung! Wählen Sie das Formular oder das Benutzersteuerelement aus, und ändern Sie den Wert der Localizable-Eigenschaft in true. Bearbeiten Sie die Resx-Datei und unterdrücken Sie die Einträge von UserAddedColumn. Wählen Sie dann Ihr Datagrid und wählen Sie "Spalten ändern". Unterdrückt alle Spalten, die automatisch hinzugefügt wurden. Setzen Sie den Wert von Localizable auf false zurück. Dadurch kamen die automatisch hinzugefügten Spalten nie auf mein Raster zurück.

Möglicherweise müssen Sie das Formular/Benutzersteuerelement speichern und die Entwurfsregisterkarte zwischen den einzelnen Operationen schließen.

Verwandte Themen