Discussion:
DataGridView - Spaltenbreite
(zu alt für eine Antwort)
Manfred Zirk
2008-11-18 19:18:01 UTC
Permalink
Hallo Leute,

ich habe ein DataGridView mit mehreren Spalten.
Die Spaltenbreite ist bei allen Spalten bis auf die letzte Spalte auf
"AllCells" eingestellt.
Die letzte Spalte steht auf "Fill"

Jetzt würde ich erwarten, das die Spaltenbreite sich in jeder Spalte außer
der letzten Spalte nach der Breite des jeweils breitesten Zellinhalts richtet.

Passiert aber nicht so richtig. Tatsächlich werden die ersten Spalten
umgebrochen, obwohl der Wrapmode auf False steht.
Trotzdem wird die letzte Spalte verbreitert.

Ist für mich irgendwie nicht nachvollziehbar.

Hat jemand einen Tip, warum die Spaltenbreiten anscheinend ein Eigenleben
haben.

Grüße

Manfred
Peter Götz
2008-11-19 07:21:05 UTC
Permalink
Hallo Manfred,
Post by Manfred Zirk
ich habe ein DataGridView mit mehreren Spalten.
Die Spaltenbreite ist bei allen Spalten bis auf die
letzte Spalte auf "AllCells" eingestellt.
Die letzte Spalte steht auf "Fill"
Wie sieht das denn in konkretem Code aus?
Post by Manfred Zirk
Jetzt würde ich erwarten, das die Spaltenbreite sich
in jeder Spalte außer der letzten Spalte nach der
Breite des jeweils breitesten Zellinhalts richtet.
Vorausgesetzt dass die ersten Spalten die Einstellung

DGV.Columns(x).AutoSizeMode = _
DataGridViewAutoSizeColumnMode.AllCells

haben und die letzte Spalte die Einstellung

DGV.Columns(y).AutoSizeMode = _
DataGridViewAutoSizeColumnMode.Fill

hat, sollten sich die Spaltenbreiten wie gewünscht einstellen.
Post by Manfred Zirk
Passiert aber nicht so richtig. Tatsächlich werden
die ersten Spalten umgebrochen, obwohl der
Wrapmode auf False steht.
Trotzdem wird die letzte Spalte verbreitert.
Dieses Verhalten kann ich hier so nicht nachvollziehen.
Post by Manfred Zirk
Ist für mich irgendwie nicht nachvollziehbar.
Ohne Deinen konkreten Code zu kennen ist es kaum
möglich, eine Fehlerursache zu erkennen.
Post by Manfred Zirk
Hat jemand einen Tip, warum die Spaltenbreiten
anscheinend ein Eigenleben haben.
Hier mal ein Beispiel bei dem 2 von 3 Spalten an den
jeweils längsten Text angepasst werden und die 3. (rechte)
Spalte den verbleibenden Raum ausfüllt.

' /// Code in einer leeren Form
Public Class Form1
Private WithEvents DGV As DataGridView
Private mDT As DataTable
Private mDV As DataView

Private Sub Form1_Load _
(ByVal sender As System.Object, _
ByVal e As System.EventArgs _
) Handles MyBase.Load

DGV = New DataGridView
DGV.Dock = DockStyle.Fill
Me.Controls.Add(DGV)

CreateData()

With DGV
.DefaultCellStyle.Font = _
New Font("Arial", 12)

.ColumnHeadersDefaultCellStyle.Font = _
New Font("Arial", 8, FontStyle.Bold)

.DataSource = mDV

.Columns(0).AutoSizeMode = _
DataGridViewAutoSizeColumnMode.AllCells

.Columns(1).AutoSizeMode = _
DataGridViewAutoSizeColumnMode.AllCells

.Columns(2).AutoSizeMode = _
DataGridViewAutoSizeColumnMode.Fill

.AutoResizeColumns()
End With

End Sub

Private Sub CreateData()
Dim i As Integer
Dim DR As DataRow

mDT = New DataTable
With mDT
.Columns.Add("ID", GetType(Integer))
.Columns.Add("SText", GetType(String))
.Columns.Add("LText", GetType(String))

For i = 1 To 12
DR = .NewRow
DR.Item(0) = i
DR.Item(1) = MonthName(i, True)
DR.Item(2) = MonthName(i, False)
.Rows.Add(DR)
Next
.AcceptChanges()
End With

mDV = New DataView(mDT)
End Sub
End Class
' \\\ E N T E

Mehr Beispiele zum DataGridView findest Du unter
www.gssg.de -> Visual Basic -> VB.net


Gruß aus St.Georgen
Peter Götz
www.gssg.de (mit VB-Tipps u. Beispielprogrammen)
Post by Manfred Zirk
Grüße
Manfred
Manfred Zirk
2008-11-19 13:30:05 UTC
Permalink
Post by Peter Götz
Hallo Manfred,
Hier mal ein Beispiel bei dem 2 von 3 Spalten an den
jeweils längsten Text angepasst werden und die 3. (rechte)
Spalte den verbleibenden Raum ausfüllt.
' /// Code in einer leeren Form
Public Class Form1
Private WithEvents DGV As DataGridView
Private mDT As DataTable
Private mDV As DataView
Private Sub Form1_Load _
(ByVal sender As System.Object, _
ByVal e As System.EventArgs _
) Handles MyBase.Load
DGV = New DataGridView
DGV.Dock = DockStyle.Fill
Me.Controls.Add(DGV)
CreateData()
With DGV
.DefaultCellStyle.Font = _
New Font("Arial", 12)
.ColumnHeadersDefaultCellStyle.Font = _
New Font("Arial", 8, FontStyle.Bold)
.DataSource = mDV
.Columns(0).AutoSizeMode = _
DataGridViewAutoSizeColumnMode.AllCells
.Columns(1).AutoSizeMode = _
DataGridViewAutoSizeColumnMode.AllCells
.Columns(2).AutoSizeMode = _
DataGridViewAutoSizeColumnMode.Fill
.AutoResizeColumns()
End With
End Sub
Private Sub CreateData()
Dim i As Integer
Dim DR As DataRow
mDT = New DataTable
With mDT
.Columns.Add("ID", GetType(Integer))
.Columns.Add("SText", GetType(String))
.Columns.Add("LText", GetType(String))
For i = 1 To 12
DR = .NewRow
DR.Item(0) = i
DR.Item(1) = MonthName(i, True)
DR.Item(2) = MonthName(i, False)
.Rows.Add(DR)
Next
.AcceptChanges()
End With
mDV = New DataView(mDT)
End Sub
End Class
' \\\ E N T E
Mehr Beispiele zum DataGridView findest Du unter
www.gssg.de -> Visual Basic -> VB.net
Gruß aus St.Georgen
Peter Götz
www.gssg.de (mit VB-Tipps u. Beispielprogrammen)
Post by Manfred Zirk
Grüße
Manfred
Hallo Peter,
Danke für die Hilfe, bei mir lag es daran, das ich im Formular für die
Spalteneigenschaften pauschal den Umbruch aktiviert hatte.
Das kann dann natürlich nicht so funktionieren.

Den Spaltenaufbau habe ich so wie du gemacht.
Automatische Breite über den breitsten Zellinhalt und die letzte Spalte mit
Fill.
Es funktioniert will es soll.
Allerdings passe ich bei mir dann auch das Formular von der Größe her an:

Private Sub MainformShowTable_Load(ByVal sender As Object, ByVal e As
System.EventArgs) Handles Me.Load

' // Hauptroutine, baut das Formular auf und lädt die Daten für die
erste Anzeige.

Dim counterColumn As Integer = 0
Dim counterRow As Integer = 0
Dim checkEntryRow As Boolean = False
Dim buffer As Integer = 0
Dim controlListEntry As String = Nothing
Dim counter As Integer = Nothing

Try
' Startwerte
Me.ToolStripStatusLabel.Font = _Font
Me.ToolStripStatusLabel.Text = ToolStripStatusLabelDefaultText

' Test der übergebenen Parameter
If DataTableColumnHeaders.Count = 0 _
Or dataTable.Rows.Count = 0 _
Or dataTable.Columns.Count = 0 _
Or dataTable.Columns.Count <> DataTableColumnHeaders.Count _
Then
Me.LabelTableTitel.Text = "Keine Liste ausgewählt"
Me.DataGridView1.Visible = False
Me.Button_OK.Enabled = False
Exit Sub
End If

' DataGridView, Spalten erzeugen.
' Anzahl der anzuzeigenden Spalten ermitten, überflüssige
Spalten ausblenden.
For counterColumn = 0 To Me.DataGridView1.Columns.Count - 1
' Die letzte anzuzeigende Spalte füllt den verbleibenden
Plart rechts im DataGridView.
If Me.DataGridView1.Columns(counterColumn).Index =
DataTableColumnHeaders.Count - 1 Then
Me.DataGridView1.Columns(counterColumn).AutoSizeMode =
DataGridViewAutoSizeColumnMode.Fill

Me.DataGridView1.Columns(counterColumn).DefaultCellStyle.WrapMode =
DataGridViewTriState.True
End If

' Spaltenheader eintragen.
If Me.DataGridView1.Columns(counterColumn).Index <=
DataTableColumnHeaders.Count - 1 Then
Me.DataGridView1.Columns(counterColumn).HeaderText =
DataTableColumnHeaders.Item(counterColumn + 1).ToString
End If

' Nicht benötigte Spalten ausblenden.
If Me.DataGridView1.Columns(counterColumn).Index >
DataTableColumnHeaders.Count - 1 Then
Me.DataGridView1.Columns(counterColumn).Width = 0
Me.DataGridView1.Columns(counterColumn).Visible = False
End If
Next counterColumn

' Daten hinzufügen
For counterRow = 0 To dataTable.Rows.Count - 1
Me.DataGridView1.Rows.Add()

For counterColumn = 0 To dataTable.Columns.Count - 1

If counterColumn = 0 Then

If ControlList.Count > 0 Then
For Each controlListEntry In ControlList
checkEntryRow = False
If controlListEntry =
dataTable.Rows(counterRow).Item(counterColumn).ToString Then
checkEntryRow = True
Exit For
End If
Next controlListEntry

If checkEntryRow = True Then
Me.DataGridView1.Rows(counterRow -
1).Cells(counterColumn).Value =
dataTable.Rows(counterRow).Item(counterColumn).ToString
Else
Me.DataGridView1.Rows(counterRow -
1).Cells(counterColumn).Value =
dataTable.Rows(counterRow).Item(counterColumn).ToString
Me.DataGridView1.Rows(counterRow -
1).DefaultCellStyle.BackColor = SystemColors.Info
Me.DataGridView1.Rows(counterRow -
1).DefaultCellStyle.ForeColor = SystemColors.GrayText
Me.DataGridView1.Rows(counterRow -
1).Cells(0).Value = String.Empty
End If
End If
End If

' Felder befüllen.
If counterColumn = 1 Then
' Eintrag Nr. als Zahl übergeben zum Sortieren!

Me.DataGridView1.Rows(counterRow).Cells(counterColumn).Value =
dataTable.Rows(counterRow).Item(counterColumn)
Else

Me.DataGridView1.Rows(counterRow).Cells(counterColumn).Value =
dataTable.Rows(counterRow).Item(counterColumn).ToString
End If

If counterColumn = 0 And
dataTable.Rows(counterRow).Item(0).ToString = Me.TextBoxStartValue.Text Then
Me.DataGridView1.CurrentCell =
Me.DataGridView1.Rows(counterRow).Cells(1)
End If

' Enthält das erste Feld keine Daten, Zeile umfärben.
If counterColumn = 0 And
dataTable.Rows(counterRow).Item(0).ToString = String.Empty Then
' Reihe ohne auswählbare Daten.

Me.DataGridView1.Rows(counterRow).DefaultCellStyle.BackColor =
SystemColors.Info

Me.DataGridView1.Rows(counterRow).DefaultCellStyle.ForeColor =
SystemColors.GrayText

Me.DataGridView1.Rows(counterRow).Cells(1).Style.ForeColor = SystemColors.Info
End If

Next counterColumn
Next counterRow

' Breite einstellen.
For counterColumn = 1 To DataTableColumnHeaders.Count - 1
If Me.DataGridView1.Columns(counterColumn).Visible = True Then
buffer = buffer +
Me.DataGridView1.Columns(counterColumn).Width +
Me.DataGridView1.Columns(counterColumn).DividerWidth
End If
Next counterColumn
Me.DataGridView1.Width = buffer + Me.DataGridView1.RowHeadersWidth

' Höhe einstellen.
buffer = 0
Dim _MaxRows As Integer = 0

If Me.DataGridView1.RowCount > 35 Then
_MaxRows = 35
Me.DataGridView1.ScrollBars = ScrollBars.Vertical
Else
_MaxRows = Me.DataGridView1.RowCount
End If

For counterRow = 0 To _MaxRows - 1

If Me.DataGridView1.Rows(counterRow).Visible = True Then
buffer = buffer +
Me.DataGridView1.Rows(counterRow).Height +
Me.DataGridView1.Rows(counterRow).DividerHeight
End If
Next counterRow
Me.DataGridView1.Height = buffer +
Me.DataGridView1.ColumnHeadersHeight

' Falls vorhanden, passenden Eintrag aus der Liste auswählen.
' Rückgabewert voreinstellen.
If Me.TextBoxStartValue.Text <> String.Empty Then
For Each _Row As System.Windows.Forms.DataGridViewRow In
Me.DataGridView1.Rows
If CType(_Row.Cells(0).Value, String) =
Me.TextBoxStartValue.Text Then
Me.TextBoxReturnValue.Text = Me.TextBoxStartValue.Text
_Row.Selected = True
Exit For
End If
Next _Row
Else
Me.TextBoxReturnValue.Text = String.Empty
End If

' Formular anpassen.
Me.Height = Me.DataGridView1.Height + 70 + 110
Me.Update()
If ValueValidate = True Then
Me.ValidateChildren()
End If

Catch ex As System.Exception
AddInBasics.MessageBoxes.ShowErrorMessage(ex, Nothing)
Me.Close()

End Try

End Sub

Grüße

Manfred
Peter Götz
2008-11-19 15:02:52 UTC
Permalink
Hallo Manfred,
Post by Manfred Zirk
Allerdings passe ich bei mir dann auch das Formular
Das mache ich in meinem Beispiel aus der vorigen
Posting doch auch per DGV.Dock = Fill.
Man könnte eine autom. Anpassung der Gridgrösse
auch mit Hilfe der Anchor-Eigenschaft (Left or Top or
Right or Bottom) bewirken.
Post by Manfred Zirk
Private Sub MainformShowTable_Load _
(ByVal sender As Object, _
ByVal e As System.EventArgs _
) Handles Me.Load
Deinen nachfolgenden Code lasse ich mal weg, da er
so gut wie nicht lesbar ist und letztlich durch deutlich
weniger Codezeilen ersetzbar wäre.

Um Deine Daten im DGV sichtbar zu machen brauchst Du
doch nur die DataTable, welche Deine Daten enthält an
DataGridView.DataSource zu binden

Dim DT as DataTable
Dim DV as DataView
DV = New DataView(DT)
DataGridView1.DataSource = DV

Um nun die äusserste rechte Spalte raumfüllend und die
übrigen angepasst an die Textbreite erscheinen zu lassen
genügt ein

Dim i as integer
For i = 0 to DGV.Columns.count -2
DGV.Columns(i).AutoSizeMode = _
DataGridViewAutoSizeColumnMode.AllCells
Next
DGV.Columns(DGV.Columns.Count-1).AutoSizeMode = _
DataGridViewAutoSizeColumnMode.Fill

Spaltenheader brauchst Du nur dann zu vergeben, wenn sie
von dem Spaltennamen der DataTable abweichen sollen.

Ich denke, Du solltest Deinen Code schon noch mal
gründlich überarbeiten und auch auf deutlich bessere
Lesbarkeit achten.

Gruß aus St.Georgen
Peter Götz
www.gssg.de (mit VB-Tipps u. Beispielprogrammen)
Manfred Zirk
2008-11-19 16:58:05 UTC
Permalink
Hallo Peter,
Post by Peter Götz
Das mache ich in meinem Beispiel aus der vorigen
Posting doch auch per DGV.Dock = Fill.
Man könnte eine autom. Anpassung der Gridgrösse
auch mit Hilfe der Anchor-Eigenschaft (Left or Top or
Right or Bottom) bewirken.
Ich werde da mit dem automatischen Anpassungd er Gridgröße nochnmal probieren.
Post by Peter Götz
Um Deine Daten im DGV sichtbar zu machen brauchst Du
doch nur die DataTable, welche Deine Daten enthält an
DataGridView.DataSource zu binden
Dim DT as DataTable
Dim DV as DataView
DV = New DataView(DT)
DataGridView1.DataSource = DV
Danke für den Hinweis, ich wusste nicht, das man auf diese Weise ein
DataGridView
an eine DataTable binden kann.
Das BindingSource-Objekt im Formular kann anscheinend mit DataTables nichts
anfangen.
Post by Peter Götz
Um nun die äusserste rechte Spalte raumfüllend und die
übrigen angepasst an die Textbreite erscheinen zu lassen
genügt ein
Dim i as integer
For i = 0 to DGV.Columns.count -2
DGV.Columns(i).AutoSizeMode = _
DataGridViewAutoSizeColumnMode.AllCells
Next
DGV.Columns(DGV.Columns.Count-1).AutoSizeMode = _
DataGridViewAutoSizeColumnMode.Fill
Spaltenheader brauchst Du nur dann zu vergeben, wenn sie
von dem Spaltennamen der DataTable abweichen sollen.
Ich habe in der Access-Tabelle Spaltennamen vergeben, z.B. itemNumber.
Leider kommt die zugehörige Beschriftung der Spalten natürlich nicht mit,
"Eintrag-Nr.", wenn man eine Abfrage erstellt und sich den den SQL-Text, den
Access fabriziert hat, ansieht.
Also kann man die gewünschte Beschriftung in .HeaderText der Columns wieder
neu eintragen oder kann man mit SQL auch die Beschriftung der Spalte lesen?
Post by Peter Götz
Ich denke, Du solltest Deinen Code schon noch mal
gründlich überarbeiten und auch auf deutlich bessere
Lesbarkeit achten.
Ich werde mir Mühe geben... ;-)
Post by Peter Götz
Gruß aus St.Georgen
Peter Götz
www.gssg.de (mit VB-Tipps u. Beispielprogrammen)
Grüße

Manfred
Peter Götz
2008-11-20 07:43:17 UTC
Permalink
Hallo Manfred,
Post by Manfred Zirk
Ich werde da mit dem automatischen Anpassungd er
Gridgröße nochnmal probieren.
Du solltest Dir vielleicht doch mal die DataGridView-
Beispiele unter

www.gssg.de -> Visual Basic -> VB.net

ansehen in denen u.a. auch das DGV autom. an die
jeweils akt. Formgrösse angepasst wird, wozu ausser
dem Setzen der Anchor-Eigenschaft keinerlei Code
nötig ist.
Post by Manfred Zirk
Post by Peter Götz
Um Deine Daten im DGV sichtbar zu machen brauchst Du
doch nur die DataTable, welche Deine Daten enthält an
DataGridView.DataSource zu binden
Dim DT as DataTable
Dim DV as DataView
DV = New DataView(DT)
DataGridView1.DataSource = DV
Danke für den Hinweis, ich wusste nicht, das man auf diese Weise ein
DataGridView an eine DataTable binden kann.
Da wäre aber dann doch mal ein Blick in die Online-Hilfe
zum DataGridView-Control und dessen
DataSource-Eigenschaft empfehlenswert.
Post by Manfred Zirk
Das BindingSource-Objekt im Formular kann anscheinend
mit DataTables nichts anfangen.
Wie kommst Du denn darauf?
Eine BindingSource ist letztlich nichts weiter als ein
Objekt, welches u.a. eine DataSource (z.B. DataTable),
eine DataView (BS.List) und einen CurrencyManager
kapselt.

Diese Objekte kannst Du auch direkt, ohne Binding-
Source verwenden und siehst dann viel deutlicher
wie DataTable, DataView u. CurrencyManager
zusammenarbeiten.

... schnipp...
Post by Manfred Zirk
Post by Peter Götz
Spaltenheader brauchst Du nur dann zu vergeben, wenn sie
von dem Spaltennamen der DataTable abweichen sollen.
Ich habe in der Access-Tabelle Spaltennamen vergeben,
z.B. itemNumber.
Leider kommt die zugehörige Beschriftung der Spalten
natürlich nicht mit, "Eintrag-Nr.", wenn man eine Abfrage
erstellt und sich den den SQL-Text, den Access fabriziert
hat, ansieht.
Die Spaltennamen in Access sind Access-interne
Eigenschaften. Die kannst Du nich mit einem Select-
Statement auslesen. Dazu müsstest Du die alten
DAO-Properties bemühen.
Post by Manfred Zirk
Also kann man die gewünschte Beschriftung in .HeaderText
der Columns wieder neu eintragen
Und warum benennst Du die Felder in Access nicht
gleich so, wie sie auch in den ColumnHeaders
Deines Grids erscheinen sollen?
Post by Manfred Zirk
oder kann man mit SQL auch die Beschriftung
der Spalte lesen?
Nein.
s.oben: DAO
Vergebe in Access gleichdie richtigen Feldnamen,
dann brauchst Du keine zusätzlichen Access-
Spaltenbeschriftungen.

Gruß aus St.Georgen
Peter Götz
www.gssg.de (mit VB-Tipps u. Beispielprogrammen)

Loading...