Benutzer mit den meisten Antworten
Mit einer ForEach-Methode datagridview.Columns durchlaufen!

Frage
-
Guten Tag die Damen und Herren,
ich hätte mal eine kleine (Verständnis)-Frage!Ausgangspunkt:
Ich habe ein Datagridview, welches 5 Spalten hat, wobei die ersten 2 Spalten nicht editierbar sein sollen.Das ist meine Lösung:
d_datagridview.Columns(0).ReadOnly = True d_datagridview.Columns(1).ReadOnly = True d_datagridview.Columns(2).ReadOnly = False d_datagridview.Columns(3).ReadOnly = False d_datagridview.Columns(4).ReadOnly = False
Sowas möchte ich haben:
Array.ForEach(d_datagridview.Columns, SetProperty) Private Sub SetProperty(ByVal column As DataGridViewColumn) 'hier sollte auch code drin stehen, aber was für einer? End Sub
Hat vielleicht jemand hierfür eine schicke Lösung?
Danke im Voraus.
Antworten
-
Hallo Jo,
das wäre, wenn man denn Array.ForEach nutzen möchte:
Array.ForEach( Me.dataGridView1.Columns.Cast(Of DataGridViewColumn).ToArray(), Sub(c) c.ReadOnly = CBool(IIf(c.DisplayIndex > 1, False, True)) End Sub)
womit der die Sub den Code Deiner angedeuteten SetMethod darstellen würde.
Für den ersten Parameter gilt:
Weil kein Array vorliegt, muss man sich eines Erzeugen, was mit der Linq Erweiterungsmethoe ToArray geschieht.
Da eine DataGridViewCollection kein typisiertes IEnumerable(Of DataGridViewColumn) liefert, ist zuvor noch
eine LINQ Cast Operation erforderlich (bei Windows Forms oft erforderlich, da ohne Generika implementiert).Was dann summa sumarum dem Ganzen deutlich mehr Overhead verpasst, als es die gezeigte "normale" Variante hat.
Sinnvollere Einsatzgebiete wären eher Bereiche, wo man mit generischen Auflistungen wie List(Of T) arbeitet.
Wenn es Dich näher interessiert, solltest Dich mit LINQ beschäftigen, wo das häufiger zum Einsatz kommt.
Siehe z. B. Linq - Summierung von mehreren Spalten, wo das verwendete gruppe.Sum(Function(w) w.Wert[1..4])
konzeptionell das gleiche ist.Gruß Elmar
- Als Antwort vorgeschlagen Robert BreitenhoferModerator Donnerstag, 14. April 2011 15:25
- Als Antwort markiert Thorsten DörflerModerator Mittwoch, 27. April 2011 13:25
-
Hallo,
mit Array.ForEach wird das schon mal nicht klappen, da es sich bei der Columns-Eigenschaft um eine Auflistung handelt (und kein Array).
Allgemein betrachtet:
In einem Enumerator - und in der Hinsicht unterscheidet sich Array/List.ForEach nicht von der For Each-Anweisung von Visual Basic -
hast Du keine Möglichkeit über einen Index zuzugreifen, da eine Position nicht bereitgestellt wird.
Enumeratoren - repräsentiert über die IEnumerable(Of T) bzw. IEnumerable Schnittstelle sind die Vorläufer
einer Auflistung - respräsentiert über IList(Of T) bzw. IList und erst ist eine Position (über den Index).Weswegen man in den Fällen, wo die Index-Position entscheidend ist, besser über eine For Schleife zugreift.
Spezieller betrachtet:
Hier könnte man auf Eigenschaften wie DisplayIndex zurückgreifen, was aber nicht das gleiche wie die Position in der Auflistung ist
(sondern die aktuelle Anordnung der Spalte angibt und sich u. U. ändern könnte).
Aber der Einsatz eines Delegaten lohnt für diesen Einsatzzweck insgesamt nicht, da man über
' Optimist: Voreinstellung ist False For columIndex = 0 To 1 d_datagridview.Columns(columIndex).ReadOnly = True Next ' oder für Pessimisten: For columIndex = 0 To d_datagridview.Columns.Count - 1 d_datagridview.Columns(columIndex).ReadOnly = IIf(columnIndex > 1, False, True) Next
auf kürzerem Wege zu Ziel kommt - das ist zwar nicht so "schick" aber funktional.
Letztere Version braucht man nur, wenn ReadOnly wechselhaft ist - Voreinstellung ist dort ohnehin False,
zumindest solange die Datenquelle überhaupt bearbeitbar ist.Im allgemeinen würde ich eh keine Methode mehr implementieren sondern gleich einen Lamba-Ausdrucks verwenden
und den Compiler die Arbeit überlassen, so z. B.(was wie oben geschrieben jedoch nicht identisch ist).Sub(c) c.ReadOnly = IIf(c.DisplayIndex > 1, False, True) End Sub
Und wenn Dir was aus Deinem Umfeld einfällt, wo man das sinnvoller einsetzen kann,
gebe ich Dir auch gerne ein funktionierendes Beispiel.Gruß Elmar
- Als Antwort vorgeschlagen Robert BreitenhoferModerator Donnerstag, 14. April 2011 15:25
- Als Antwort markiert Thorsten DörflerModerator Mittwoch, 27. April 2011 13:25
Alle Antworten
-
Hallo,
mit Array.ForEach wird das schon mal nicht klappen, da es sich bei der Columns-Eigenschaft um eine Auflistung handelt (und kein Array).
Allgemein betrachtet:
In einem Enumerator - und in der Hinsicht unterscheidet sich Array/List.ForEach nicht von der For Each-Anweisung von Visual Basic -
hast Du keine Möglichkeit über einen Index zuzugreifen, da eine Position nicht bereitgestellt wird.
Enumeratoren - repräsentiert über die IEnumerable(Of T) bzw. IEnumerable Schnittstelle sind die Vorläufer
einer Auflistung - respräsentiert über IList(Of T) bzw. IList und erst ist eine Position (über den Index).Weswegen man in den Fällen, wo die Index-Position entscheidend ist, besser über eine For Schleife zugreift.
Spezieller betrachtet:
Hier könnte man auf Eigenschaften wie DisplayIndex zurückgreifen, was aber nicht das gleiche wie die Position in der Auflistung ist
(sondern die aktuelle Anordnung der Spalte angibt und sich u. U. ändern könnte).
Aber der Einsatz eines Delegaten lohnt für diesen Einsatzzweck insgesamt nicht, da man über
' Optimist: Voreinstellung ist False For columIndex = 0 To 1 d_datagridview.Columns(columIndex).ReadOnly = True Next ' oder für Pessimisten: For columIndex = 0 To d_datagridview.Columns.Count - 1 d_datagridview.Columns(columIndex).ReadOnly = IIf(columnIndex > 1, False, True) Next
auf kürzerem Wege zu Ziel kommt - das ist zwar nicht so "schick" aber funktional.
Letztere Version braucht man nur, wenn ReadOnly wechselhaft ist - Voreinstellung ist dort ohnehin False,
zumindest solange die Datenquelle überhaupt bearbeitbar ist.Im allgemeinen würde ich eh keine Methode mehr implementieren sondern gleich einen Lamba-Ausdrucks verwenden
und den Compiler die Arbeit überlassen, so z. B.(was wie oben geschrieben jedoch nicht identisch ist).Sub(c) c.ReadOnly = IIf(c.DisplayIndex > 1, False, True) End Sub
Und wenn Dir was aus Deinem Umfeld einfällt, wo man das sinnvoller einsetzen kann,
gebe ich Dir auch gerne ein funktionierendes Beispiel.Gruß Elmar
- Als Antwort vorgeschlagen Robert BreitenhoferModerator Donnerstag, 14. April 2011 15:25
- Als Antwort markiert Thorsten DörflerModerator Mittwoch, 27. April 2011 13:25
-
Hallo Jo,
das wäre, wenn man denn Array.ForEach nutzen möchte:
Array.ForEach( Me.dataGridView1.Columns.Cast(Of DataGridViewColumn).ToArray(), Sub(c) c.ReadOnly = CBool(IIf(c.DisplayIndex > 1, False, True)) End Sub)
womit der die Sub den Code Deiner angedeuteten SetMethod darstellen würde.
Für den ersten Parameter gilt:
Weil kein Array vorliegt, muss man sich eines Erzeugen, was mit der Linq Erweiterungsmethoe ToArray geschieht.
Da eine DataGridViewCollection kein typisiertes IEnumerable(Of DataGridViewColumn) liefert, ist zuvor noch
eine LINQ Cast Operation erforderlich (bei Windows Forms oft erforderlich, da ohne Generika implementiert).Was dann summa sumarum dem Ganzen deutlich mehr Overhead verpasst, als es die gezeigte "normale" Variante hat.
Sinnvollere Einsatzgebiete wären eher Bereiche, wo man mit generischen Auflistungen wie List(Of T) arbeitet.
Wenn es Dich näher interessiert, solltest Dich mit LINQ beschäftigen, wo das häufiger zum Einsatz kommt.
Siehe z. B. Linq - Summierung von mehreren Spalten, wo das verwendete gruppe.Sum(Function(w) w.Wert[1..4])
konzeptionell das gleiche ist.Gruß Elmar
- Als Antwort vorgeschlagen Robert BreitenhoferModerator Donnerstag, 14. April 2011 15:25
- Als Antwort markiert Thorsten DörflerModerator Mittwoch, 27. April 2011 13:25