none
VB.NET WinForms DataGridView Hidden Columns erscheinen wieder RRS feed

  • Frage

  • Hallo,

    Kleines Problem.

    Ich verwende verschiedene DataGridViews die mittels LINQtoSQLclass mit Daten befüllt werden. Ich habe bei allen GridViews die erste Spalte (ist in meinem Fall immer eine ID und Primary Key) versteckt. Sobald ich meine Anwendung debugge und ausführe erscheinen die Spalten wieder. Warum?

    Donnerstag, 14. Juni 2012 22:31

Antworten

  • Ich habe mir mal den Beitrag angeschaut. Ich werde da wieder in meiner Voreingenommenheit gegenüber den Automatismen der Designer bestätigt.
     
    Der Designer erzeugt eine Folge von Befehlen, die dazu führen, dass es beim Zuweisen der Datenquelle an die gebundene BindingSource zum Verändern der vorher eingestellten Visible-Eigenschaft kommen kann. Wenn die Folge des Einbettens der Steuerelemente so verändert wird, dass von oben nach unten (zuerst die äußeren Controls-Auflistungen) zugewiesen wird, tritt dieses Erscheinungsbild nicht auf. Deshalb war das Verhalten in meiner Demo auch nicht sichtbar.
     
    Nachfolgend mal eine Demo zur Verdeutlichung. Tausche einfach mal die Reihenfolge der Zuweisung des Grids und des TabControls.
     
    Public Class Form1
    
      Private Sub Form1_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load
        '
        Dim tc As New TabControl With {.Dock = DockStyle.Fill}
        Dim tp1 As New TabPage With {.Text = "Page 1"}
        Dim tp2 As New TabPage With {.Text = "Page 2"}
        Dim dgv2 As New DataGridView With {.AutoGenerateColumns = False, .Dock = DockStyle.Fill}
        Dim col1 As New DataGridViewTextBoxColumn With {.DataPropertyName = "Name", .HeaderText = "Name", .Visible = False}
        Dim col2 As New DataGridViewTextBoxColumn With {.DataPropertyName = "Vorname", .HeaderText = "Vorname"}
        Dim ds As New DataSet1
        Dim bs As New BindingSource
        '
        bs.DataMember = "Tab1"
        bs.DataSource = ds
        '
        dgv2.Columns.AddRange(New System.Windows.Forms.DataGridViewColumn() {col1, col2})
        dgv2.DataSource = bs
        '
        tc.TabPages.AddRange(New TabPage() {tp1, tp2})
        '
        ' Reihenfolge mit Problem
        tp2.Controls.Add(dgv2)
        Me.Controls.Add(tc)
        '
        '' Reihenfolge ohne Problem
        'Me.Controls.Add(tc)
        'tp2.Controls.Add(dgv2)
        '
        Call (New DataSet1TableAdapters.Tab1TableAdapter).Fill(ds.Tab1)
      End Sub
    
    End Class
    

    --
    Viele Gruesse
    Peter

    • Als Antwort vorgeschlagen Peter Fleischer Montag, 18. Juni 2012 02:50
    • Als Antwort markiert megahairpin Montag, 18. Juni 2012 08:47
    Sonntag, 17. Juni 2012 19:02

Alle Antworten

  • Die Spalten können beispielsweise erscheinen, wenn AutoGenerateColumns auf true steht. Dann werden die Spalten, die im Design fehlen, in der Datenquelle aber vorhanden sind, automatisch hinzugefügt.
     
    --
    Viele Gruesse
    Peter
    • Als Antwort vorgeschlagen Peter Fleischer Samstag, 16. Juni 2012 08:51
    • Nicht als Antwort vorgeschlagen megahairpin Samstag, 16. Juni 2012 10:14
    Freitag, 15. Juni 2012 07:49
  • Hallo Herr Fleischer,

    Ich setze AutoGenerateColumns auf FALSE im FormsLoad Ereignis. Trotzdem wird weiterhin die ausgeblendete Spalte angezeigt?!!?

    Samstag, 16. Juni 2012 10:14
  • Es kann sein, dass das Setzen der Eigenschaft im Form_Load zu spät ist, wenn vorher bereits gebunden wurde.
     
    --
    Viele Gruesse
    Peter
    Samstag, 16. Juni 2012 10:53
  • Ich habe beide Szenarien probiert einmal vor dem binden der Daten und einmal danach: 

    Tbl_projectDataGridView.AutoGenerateColumns = False
            'Füllt die Datentabelle tbl_projects und alle Child-Tabellen
            Me.Tbl_projectBindingSourceAktuell.DataSource = db.tbl_projects

    Nichts passiert...

    Samstag, 16. Juni 2012 11:08
  • Wenn nichts passiert, wo ist dann das Problem? Was soll den passieren?
     
    --
    Viele Gruesse
    Peter
    Samstag, 16. Juni 2012 14:44
  • Es sollen die selben DataGridView Spalten erscheinen die auch im Designer festgelegt wurden und nicht einfach alle.

    Hab ein bisschen gegoogelt und manche Leute meinten das es wohl ein BUG von VS ist.

    Samstag, 16. Juni 2012 19:26
  • Wenn zum Zeitpunkt der Bindung die Eigenschaft AutoGenerateColumns auf False steht, dann werden keine Spalten automatisch hinzugefügt. Falls das wirklich ein Bug sein sollte, dann wäre eine Demo und eine Meldung an microsoft eine gute Entscheidung. Mir ist solch ein Probleme in allen meinen bisherigen Anwendungen nicht vorgekommen.
     
    --
    Viele Gruesse
    Peter
    Samstag, 16. Juni 2012 19:39
  • Wir kommen dem Problem näher :)

    Ich verwende mehrere DataGridViews, diese sind auf verschiedenen Tabs eines TabControls. Der erste Tab beinhaltet kein DataGridView. Wenn ich nun den ersten Tab nach hinten schiebe und so mein Projekt Datagridview auf der ersten Tabseite steht, werden die richtigen von mir im Designer eingestellten Spalten angezeigt. Auf allen anderen Tabs jedoch nicht. Die Daten kommen alle aus einer LINQtoSQLclass mit einer Master- und 4 Child Tabellen die im Form Load Event gebunden werden.

    Ich hab inzwischen auch versucht in fast allen Events des Datagridviews die

    .AutoGenerateColumns = False

    zu setzen jedoch hat dies keine Auswirkung gezeigt.

    Samstag, 16. Juni 2012 20:08
  • Ich habe anhand Deiner Schilderungen das mal nachgestellt und es funktioniert problemlos. Was machst Du anders?
     
    Hier meine Demo:
     
    Public Class Form1
    
      Private tc As New TabControl With {.Dock = DockStyle.Fill}
      Private tp1 As New TabPage With {.Text = "Page 1"}
      Private tp2 As New TabPage With {.Text = "Page 2"}
      Private tp3 As New TabPage With {.Text = "Page 3"}
      Private tp4 As New TabPage With {.Text = "Page 4"}
    
      Private dgv1 As New DataGridView With {.AutoGenerateColumns = False, .Dock = DockStyle.Fill}
      Private dgv2 As New DataGridView With {.AutoGenerateColumns = False, .Dock = DockStyle.Fill}
      Private dgv3 As New DataGridView With {.AutoGenerateColumns = False, .Dock = DockStyle.Fill}
      Private dgv4 As New DataGridView With {.AutoGenerateColumns = False, .Dock = DockStyle.Fill}
    
      Private Sub Form1_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load
        Me.Controls.Add(tc)
        tc.TabPages.AddRange(New TabPage() {tp1, tp2, tp3, tp4})
        tp1.Controls.Add(dgv1)
        tp2.Controls.Add(dgv2)
        tp3.Controls.Add(dgv3)
        tp4.Controls.Add(dgv4)
        dgv1.Columns.Add(New DataGridViewTextBoxColumn With {.HeaderText = "Name", ..DataPropertyName = "Name"})
        dgv2.Columns.Add(New DataGridViewTextBoxColumn With {.HeaderText = "Name", ..DataPropertyName = "Name"})
        dgv3.Columns.Add(New DataGridViewTextBoxColumn With {.HeaderText = "Name", ..DataPropertyName = "Name"})
        dgv4.Columns.Add(New DataGridViewTextBoxColumn With {.HeaderText = "Name", ..DataPropertyName = "Name"})
        Dim dc As New DataClasses1DataContext
        dgv1.DataSource = From itm In dc.Tab1s
        dgv2.DataSource = From itm In dc.Tab1s
        dgv3.DataSource = From itm In dc.Tab1s
        dgv4.DataSource = From itm In dc.Tab1s
      End Sub
    
    End Class
    

    --
    Viele Gruesse
    Peter

    Samstag, 16. Juni 2012 20:58
  • Ich erstelle die Spalten nicht per Code sondern habe die DataGridViews einfach aus den DataSources auf meine Form gezogen und führe dann im Form Load folgendes aus um die Grids mit Daten zu füllen:

    Me.Tbl_projectBindingSourceAktuell.DataSource = db.tbl_projects

    Vielleicht liegt hier das Problem das ich das Befüllen nicht Codeseitig erledige.

    Hier ist ein ähnlicher Thread:

    http://social.msdn.microsoft.com/forums/en-US/winformsdatacontrols/thread/25380982-f5c8-44bc-93f7-23d8ccb9ab49

    Schon mal Danke für den Support!

    Samstag, 16. Juni 2012 21:14
  • Es ist egal, ob Du die Steuerelemente mit eigenem Code im Form_Load erzeugst oder die vom Designer dafür erzeugten Befehle nutzt. Der Designer schreibt die Befehle dafür in die InitializeComponent-Methode, die vor dem Form_Load im Konstruktor aufgerufen werden. Dort steht dann auch die Zuweisung  von AutoGenerateColumns=false, die Du im Designer eingestellt hast. Erst später wird Form_Load aufgerufen und die von Dir dort eingebaute Zuweisung der DataSource ausgeführt. Damit hast Du genau das in meinem Beispielcode gezeigte Szenario.

    In dem von Dir genannten Link ist eindeutig ausgewiesen, dass mit AutoGenerateColumns=false das Problem gelöst wurde.

    --
    Viele Gruesse
    Peter


    Sonntag, 17. Juni 2012 03:38
  • Das Problem muss irgendwie am TabControl liegen. Wenn die Grids auf der ersten TabSeite liegen werden die Spalten richtig angezeigt, wenn ein Gird auf einer anderen Seite liegt werden wieder alle Spalten angezeigt. Muss ich bei irgendeinem Change Ereigniss o.ä. das AutoGenerateColumns=false nochmals setzen?
    Sonntag, 17. Juni 2012 10:05
  • Egal wo das Grid liegt, muss vor der Zuweisung der DataSource AutoGenerateColumns auf False gesetzt werden, um zu verhindern, dass die für nicht dargestellte Eigenschaften der Datenquelle zusätzliche Spalten generiert werden.
     
    Du kannst ja mal prüfen, wo der Designer die Zuweisung zu AutoGenerateColumns und die Zuweisung zur DataSource platziert hat. Mit einem Haltepunkt auf die Anweisung zur Zuweisung der DataSource kannst Du ja prüfen, wie AutogenerateColumns eingestellt ist.
     
    --
    Viele Gruesse
    Peter
    Sonntag, 17. Juni 2012 12:11
  • AutoGenerateColumns  wird auf False gesezt und bleibt auch auf False slebst im Paint-Event.... trotzdem erscheinen immer alle Spalten. Die Spalten Codeseitig ausblenden ist die einzige Möglichkeit die ich bisher sehe. Ich verstehe es einfach nicht....

    Nachtrag:

    Ich hab das Szenario mal in einer neuen Form nachgebaut selbes Proble.

    Form ==> TabControl mit 2 Tabs => Tab 1 enthält MasterTabelle => Tab2 enthält Child Tabelle

    Public Class testtest
    
        Dim db As New BuateilTOZielmassDataContext
    
        Private Sub testtest_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load
    
            Me.Tbl_projectBindingSource.DataSource = db.tbl_projects
    
        End Sub
    End Class

    Resultat: Im ersten GridView werden die ID's wie gewünscht ausgeblendet im zweiten Grid nicht....

    • Bearbeitet megahairpin Sonntag, 17. Juni 2012 13:30 Zusatz
    Sonntag, 17. Juni 2012 13:23
  • Welches Event Du betrachtest ist völlig gleichgültig. Von Beduetung ist – wie auch in dem von Dir zitierten Link dargestellt – die Reihenfolge der Bindung an das DataGridView. Zuerst ist AutogenerateColumns auf False zu setzen und erst dann der DataSource-Eigenschaft die Datenquelle zuzuweisen.
     
    Aus den Bezeichnern in Deinem Codeschnipsel kann man schlussfolgern, dass Du ein konfigurierte BindingsSource dem DataGridView zuweist und vermutlich erst später AutoGenerateColumns auf False setzt. Die Zuweisung der Datenquelle an die BindingSource ist für das Hinzufügen der Spalten im DataGridView in diesem Fall ohne Bedeutung.
     
    --
    Viele Gruesse
    Peter
    Sonntag, 17. Juni 2012 14:38
  • Hallo,

    Es scheint wohl doch ein Bug zu sein. Wenn ich meine ID Spalte nicht als erste Spalte setze (z.B. als letzte Gridspalte) und sie dann ausblende funktioniert es einwandfrei. So werde ich es einfach machen.

    Ach ja hier wurde das Thema auch besprochen : http://groups.google.com/group/microsoft.public.dotnet.framework.windowsforms.controls/browse_thread/thread/6453c733cdb704e3/ad1afeda1ef320bb?lnk=st&q=%2Btabcontrol+%2Bdatagridview+%2Bvisible&rnum=1

    Vielen Dank für die Hilfe!

    Sonntag, 17. Juni 2012 15:53
  • Ich habe mir mal den Beitrag angeschaut. Ich werde da wieder in meiner Voreingenommenheit gegenüber den Automatismen der Designer bestätigt.
     
    Der Designer erzeugt eine Folge von Befehlen, die dazu führen, dass es beim Zuweisen der Datenquelle an die gebundene BindingSource zum Verändern der vorher eingestellten Visible-Eigenschaft kommen kann. Wenn die Folge des Einbettens der Steuerelemente so verändert wird, dass von oben nach unten (zuerst die äußeren Controls-Auflistungen) zugewiesen wird, tritt dieses Erscheinungsbild nicht auf. Deshalb war das Verhalten in meiner Demo auch nicht sichtbar.
     
    Nachfolgend mal eine Demo zur Verdeutlichung. Tausche einfach mal die Reihenfolge der Zuweisung des Grids und des TabControls.
     
    Public Class Form1
    
      Private Sub Form1_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load
        '
        Dim tc As New TabControl With {.Dock = DockStyle.Fill}
        Dim tp1 As New TabPage With {.Text = "Page 1"}
        Dim tp2 As New TabPage With {.Text = "Page 2"}
        Dim dgv2 As New DataGridView With {.AutoGenerateColumns = False, .Dock = DockStyle.Fill}
        Dim col1 As New DataGridViewTextBoxColumn With {.DataPropertyName = "Name", .HeaderText = "Name", .Visible = False}
        Dim col2 As New DataGridViewTextBoxColumn With {.DataPropertyName = "Vorname", .HeaderText = "Vorname"}
        Dim ds As New DataSet1
        Dim bs As New BindingSource
        '
        bs.DataMember = "Tab1"
        bs.DataSource = ds
        '
        dgv2.Columns.AddRange(New System.Windows.Forms.DataGridViewColumn() {col1, col2})
        dgv2.DataSource = bs
        '
        tc.TabPages.AddRange(New TabPage() {tp1, tp2})
        '
        ' Reihenfolge mit Problem
        tp2.Controls.Add(dgv2)
        Me.Controls.Add(tc)
        '
        '' Reihenfolge ohne Problem
        'Me.Controls.Add(tc)
        'tp2.Controls.Add(dgv2)
        '
        Call (New DataSet1TableAdapters.Tab1TableAdapter).Fill(ds.Tab1)
      End Sub
    
    End Class
    

    --
    Viele Gruesse
    Peter

    • Als Antwort vorgeschlagen Peter Fleischer Montag, 18. Juni 2012 02:50
    • Als Antwort markiert megahairpin Montag, 18. Juni 2012 08:47
    Sonntag, 17. Juni 2012 19:02