Autor
|
Thema: DataGridView mit Controls filtern etc. (4635 mal gelesen)
|
KMassler Ehrenmitglied V.I.P. h.c. CAD Admin + Mädchen für Alles...
Beiträge: 2657 Registriert: 06.11.2000
|
erstellt am: 08. Jul. 2014 12:12 <-- editieren / zitieren --> Unities abgeben:
Hallo Experten, ich hab da mal wieder ein Problem bzw. Fragen zum Thema Datagridview. Ich verwende das in verschiedenen Programmen, gerne auch in Verbindung zu einer SQL-Datenbank. Dabei wird die DB mit einer DataTable verknüpft und dann über ein DataView in einer DataGridView dargestellt. Das hat u.a. für mich den Vorteil, dass man die dargestellten Werte schön filtern kann Nun verwende ich das DataGridView auch öfters mal ohne Datenbank. Die Werte werden dabei direkt ohne Datatable oder Dataview in die DataGridView rein geschrieben. Dabei nutze ich auch gerne die Möglichkeiten, neben Werten bzw. Texten auch diverse Controls (Checkboxen, Images...) in die DataGridview einzufügen (s.Bild)
Nun möchte ich die Vorteile kombinieren, weiß aber nicht, wie:
- Dataview verwenden, um Filtern zu können
- Controls darstellen und manipulieren (checked, unchecked, enabled ...)
Das Problem ist, wie bringe ich die Controls in die DataTable? Oder wie filtere ich das DataGridView ohne Dataview (wäre für den aktuellen Fall am schönsten, da ich dann die ganze Befüllungslogik so lassen könnte)? ------------------ Klaus www.al-ko.com | mein Gästebuch Eine Antwort auf diesen Beitrag verfassen (mit Zitat/Zitat des Beitrags) IP |
HenryV Mitglied Konstrukteur, Engineering
Beiträge: 778 Registriert: 18.05.2005 SolidWorks 2020 x64 SP3.0 Dell Precision 5820 Intel Xeon W-2125 4x4GHz NVIDIA Quadro P2000 5GB 32GB RAM 2x Dell U2412M, 24" TFT Windows 10 Enterprise x64 21H1 Microsoft Office 365 ProPlus Microsoft Visual Studio Enterprise 2022
|
erstellt am: 10. Jul. 2014 14:38 <-- editieren / zitieren --> Unities abgeben: Nur für KMassler
Hallo Klaus Meines Wissens nach kann man ein DataGridView nicht direkt filtern, das geht nur über ein DataView als DataSource, und Controls kann man nicht in ein DataTable speichern. Hab da mal ein Beispiel gefunden, wie es gehen könnte. http://social.msdn.microsoft.com/Forums/windows/en-US/a4b73195-7631-4b0e-b028-77e138ac1b97/adding-controls-in-datatable?forum=winformsdatacontrols
Code: Public Class Form1 Dim dt As New DataTable Dim dv As New DataView Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load dt.Columns.Add("Name") dt.Columns.Add("Geschlecht") dt.Columns.Add("Geburtstadum", GetType(DataGridViewButtonCell)) dt.Columns.Add("Verheiratet", GetType(Boolean)) dv = New DataView(dt) DataGridView1.DataSource = dv DataGridView1.Columns.Remove("Geschlecht") DataGridView1.Columns.Remove("Geburtstadum") DataGridView1.Columns.Remove("Verheiratet") Dim cc As New DataGridViewComboBoxColumn() With cc .DataPropertyName = "Geschlecht" .HeaderText = "Geschlecht" .Items.Add("männlich") .Items.Add("weiblich") .Items.Add("undefiniert") End With DataGridView1.Columns.Add(cc) Dim bc As New DataGridViewButtonColumn() With bc .DataPropertyName = "Geburtstadum" .HeaderText = "Geburtstadum" End With DataGridView1.Columns.Add(bc) Dim cb As New DataGridViewCheckBoxColumn With cb .DataPropertyName = "Verheiratet" .HeaderText = "Verheiratet" End With DataGridView1.Columns.Add(cb) AddHandler DataGridView1.CellContentClick, AddressOf dgv_CellContentClick End Sub Private Sub dgv_CellContentClick(ByVal sender As Object, ByVal e As DataGridViewCellEventArgs) If e.ColumnIndex = 2 Then MessageBox.Show("The clicked row's index is " & e.RowIndex) End If End Sub Private Sub TextBox1_TextChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles TextBox1.TextChanged dv.RowFilter = "Name Like '%" & TextBox1.Text & "%'" End Sub Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click dt.Rows.Add("Ich", "männlich", Nothing, True) End Sub End Class
------------------ 21 ist nur die halbe Antwort. Eine Antwort auf diesen Beitrag verfassen (mit Zitat/Zitat des Beitrags) IP |
KMassler Ehrenmitglied V.I.P. h.c. CAD Admin + Mädchen für Alles...
Beiträge: 2657 Registriert: 06.11.2000
|
erstellt am: 10. Jul. 2014 15:30 <-- editieren / zitieren --> Unities abgeben:
Hallo Henry, das ist cool und das werde ich mit Sicherheit bei dem einen oder anderen neuen Projekt verwenden, dafür schon mal fette Us. Ob bei dem aktuellen Projekt weiß ich noch nicht, das zu ändern gibt doch arg viel Geschreibsel und Fehlergesuche... Außerdem hab ich noch 2 Probleme: 1. Wie füge ich ein ImageColumn ein, so dass- ähnlich wie bei den Beispielcontrols- diese schon bei der Erstellung und bei jeder neu hinzu gefügten Zeile antgezeigt werden?
Code: Dim pc As New DataGridViewImageColumn With pc .Image = My.Resources.BtnLupe .DataPropertyName = "Preview" .HeaderText = "Preview" End With DGV.Columns.Add(pc)
funktioniert nicht. Das Image wird nicht gezeigt. Ich könnte wohl im Button-Handler dafür sorgen, dass das Bild inder DatagridView-Zeile eingefügt wird- da es aber nicht Bestandteil der Tabelle oder der View ist, wird es sicher spätesten nach einem Filtern verloren sein. In meinem obigen Screenshots sind die Button am rechten Rand keine Buttons sondern Images. Buttons mit Bildern in dieser Größe sehen einfach nicht zufriedenstellend aus. 2. Wie füge ich solche Controls am Anfang der Zeile ein? Hier werden ja Spalten aus der DataView gelöscht und dann Ersatzspalten wieder hinzu gefügt- die kommen aber immer ans Ende. Wie füge ich welche am Anfang ein? So wie im Screenshot die Checkboxen und Images. ------------------ Klaus www.al-ko.com | mein Gästebuch Eine Antwort auf diesen Beitrag verfassen (mit Zitat/Zitat des Beitrags) IP |
HenryV Mitglied Konstrukteur, Engineering
Beiträge: 778 Registriert: 18.05.2005 SolidWorks 2020 x64 SP3.0 Dell Precision 5820 Intel Xeon W-2125 4x4GHz NVIDIA Quadro P2000 5GB 32GB RAM 2x Dell U2412M, 24" TFT Windows 10 Enterprise x64 21H1 Microsoft Office 365 ProPlus Microsoft Visual Studio Enterprise 2022
|
erstellt am: 11. Jul. 2014 12:13 <-- editieren / zitieren --> Unities abgeben: Nur für KMassler
Hallo Klaus Zu 1. Das stimmt, aber du kannst das NullValue-Bild ändern. Code: Dim pc As New DataGridViewImageColumn With pc .DefaultCellStyle.NullValue = My.Resources.BtnLupe .DataPropertyName = "Preview" .HeaderText = "Preview" End With DGV.Columns.Add(pc)
Oder du löst es über das CellFormatting-Event http://stackoverflow.com/questions/6473310/cannot-change-image-in-datagridview-winforms
Code: Private Sub DataGridView1_CellFormatting(ByVal sender As Object, ByVal e As DataGridViewCellFormattingEventArgs) Handles DataGridView1.CellFormatting ' Check if it's the Image column. If DataGridView1.Columns(e.ColumnIndex).Name = "Preview" And _ DataGridView1.Rows(e.RowIndex).Cells("Preview").Value IsNot Nothing Then e.Value = My.Resources.bild End If End Sub
Zu 2. Ändere die Reihenfolge wie das DataTable mit Spalten befüllt wird. (Diese Reihenfolge bestimmt das Hinzufügen neuer Zeilen) und setze beim Erstellen der Spalte im DGV den .DisplayIndex = 0 Gruss Andreas
------------------ 21 ist nur die halbe Antwort. Eine Antwort auf diesen Beitrag verfassen (mit Zitat/Zitat des Beitrags) IP |
KMassler Ehrenmitglied V.I.P. h.c. CAD Admin + Mädchen für Alles...
Beiträge: 2657 Registriert: 06.11.2000
|
erstellt am: 11. Jul. 2014 13:41 <-- editieren / zitieren --> Unities abgeben:
|
KMassler Ehrenmitglied V.I.P. h.c. CAD Admin + Mädchen für Alles...
Beiträge: 2657 Registriert: 06.11.2000 SolidWorks Start 1999 ** CSWP 01/2008 ** Dell Precision 7540 mobile Workstation, 64GB, Quadro RTX 3000; SWX2020 SP5; SAP/PLM+ECTR; DriveWorks Pro; Programmierung: VBA, aktuell Visual Studio 2017/VB.Net
|
erstellt am: 14. Jul. 2014 09:28 <-- editieren / zitieren --> Unities abgeben:
Hmm... weiter geht's... Die Checkboxen, Dropdownlisten etc. kann der User zur Laufzeit anklicken und die Werte verändern. Das bleibt auch nach Sortieren und Filtern in der DataGridView richtig erhalten. Aber bis jetzt sind die Images statisch, sie werden beim Erzeugen des Felds definiert. Wie kann ich die zur Laufzeit ändern? In dem Screenshot vom Anfang wird z.B. über unterschiedliche Bilder ein Disabled- bzw. Enabled-Status dargestellt. Wenn der User etwas in die Spalte "Neuer Dateiname" einträgt, ändert sich der Status auf "enabled" und entsprechend wird das Bild für die Aktion angezeigt. In unserem Beispiel möchte ich etwa zu Beginn eine ausgegraute Version des Bildes anzeigen (BtnLupeDisabled). Erst wenn der User einen Text in der Spalte "Name" eingetragen hat, soll sich das Bild zu "BtnLupe" ändern. Das würde ich in dem CellEndEdit-Event der DataGridView machen- wenn ich es könnte. Aber die Zelle hat keine Image-Eigenschaft, der ich ein Bild zuweisen könnte- obwohl die Spalte vom Typ DataGridViewImageColum ist. ------------------ Klaus www.al-ko.com | mein Gästebuch Eine Antwort auf diesen Beitrag verfassen (mit Zitat/Zitat des Beitrags) IP |
HenryV Mitglied Konstrukteur, Engineering
Beiträge: 778 Registriert: 18.05.2005 SolidWorks 2020 x64 SP3.0 Dell Precision 5820 Intel Xeon W-2125 4x4GHz NVIDIA Quadro P2000 5GB 32GB RAM 2x Dell U2412M, 24" TFT Windows 10 Enterprise x64 21H1 Microsoft Office 365 ProPlus Microsoft Visual Studio Enterprise 2022
|
erstellt am: 14. Jul. 2014 11:25 <-- editieren / zitieren --> Unities abgeben: Nur für KMassler
Hallo Klaus Falls du das CellFormatting-Event genommen hast, kann man das so machen. Code: Private Sub dataGridView1_CellFormatting(ByVal sender As Object, ByVal e As DataGridViewCellFormattingEventArgs) Handles DataGridView1.CellFormatting If Not DataGridView1.Rows(e.RowIndex).IsNewRow Then If DataGridView1.Columns(e.ColumnIndex).Name = "Preview" Then If DataGridView1.Rows(e.RowIndex).Cells("Name").Value.ToString <> "" Then e.Value = My.Resources.BtnLupe Else e.Value = My.Resources.bild End If End If Else If DataGridView1.Columns(e.ColumnIndex).Name = "Preview" And _ DataGridView1.Rows(e.RowIndex).Cells("Preview").Value IsNot Nothing Then e.Value = My.Resources.bild End If End If End SubPrivate Sub DataGridView1_CellEndEdit(ByVal sender As Object, ByVal e As System.Windows.Forms.DataGridViewCellEventArgs) Handles DataGridView1.CellEndEdit Me.Refresh() End Sub
Gruss Andreas ------------------ 21 ist nur die halbe Antwort. Eine Antwort auf diesen Beitrag verfassen (mit Zitat/Zitat des Beitrags) IP |
KMassler Ehrenmitglied V.I.P. h.c. CAD Admin + Mädchen für Alles...
Beiträge: 2657 Registriert: 06.11.2000
|
erstellt am: 17. Jul. 2014 08:51 <-- editieren / zitieren --> Unities abgeben:
Nochmal 10 U's- wenn's denn ginge Mit dem Textfeld funktioniert das wie von dir beschrieben. Wichtig ist hier das Refresh im CellEndEdit-Event. Und wichtig ist, dass jeder Spalte ein Namen zugewiesen wird- was bisher nicht der Fall war. Aus Code: Dim pc As New DataGridViewImageColumn With pc .Image = My.Resources.BtnLupe .DataPropertyName = "Preview" .HeaderText = "Preview" End With DGV.Columns.Add(pc)
muss werden Code: Dim pc As New DataGridViewImageColumn With pc .Image = My.Resources.BtnLupe .DataPropertyName = "Preview" .HeaderText = "Preview" .Name = "Preview" End With DGV.Columns.Add(pc)
Dann klappt's mit dem Nachbarn äh dem Textfeld. :) Weiter mit dem Denksport Ich habe jetzt diese Prozedur so umgestrickt, dass sie nicht auf Änderung des Textes sondern auf Änderung der Checkbox reagieren soll. Da das mit dem Namen zuerst nicht funktionert hat (s.o.), habe ich Zeilen wie diese Code: If DataGridView1.Columns(e.ColumnIndex).Name = "Preview"
ersetzt durch Code: If e.ColumnIndex = 3
nur um festzustellen, dass der Index nicht mit der dargestellten Reihenfolge übereinstimmt, sondern die Reihenfolge der Spaltenerstellung beinhaltet. Man müsste dann z.B. bei der Erstellung der Spalten dien Spaltenindex in Variablen festhalten und dann mit diesen Variablen arbeiten. Das geht, habe ich mir aber jetzt gespart und mit dem ursprünglichen Code weiter gearbeitet. Da die Spalten ja inzwischen Namen haben, ist das kein Problem mehr. (Achtung! Geänderte Bildnamen im Code) Code: Private Sub DataGridView1_CellFormatting(sender As Object, e As System.Windows.Forms.DataGridViewCellFormattingEventArgs) Handles DataGridView1.CellFormatting If Not DataGridView1.Rows(e.RowIndex).IsNewRow Then If DataGridView1.Columns(e.ColumnIndex).Name = "Preview" Then If DataGridView1.Rows(e.RowIndex).Cells("Verheiratet").Value = True Then e.Value = My.Resources.Red_CheckMark_32x32 Else e.Value = My.Resources.Gray_CheckMark_32x32 End If End If Else If DataGridView1.Columns(e.ColumnIndex).Name = "Preview" And _ DataGridView1.Rows(e.RowIndex).Cells("Preview").Value IsNot Nothing Then e.Value = My.Resources.Gray_Cancel_32x32 End If End If End Sub
Aber es gibt ein neues Problem: CellEndEdit greift hier nicht. Wo schreibe ich das Me.refresh rein, damit das Vorschaubild sofort aktualisiert wird? Ich habe alle möglichen Events probiert (CellMouseUp, MouseUp, CellValueChanged, CellStateChanged, CellClick,CellValidated, ???). Wenn überhaupt, wird das Preview-Bild erst aktualisiert, wenn ich in eine andere Zelle klicke Hab ich ein Event übersehen? ------------------ Klaus www.al-ko.com | mein Gästebuch Eine Antwort auf diesen Beitrag verfassen (mit Zitat/Zitat des Beitrags) IP |
HenryV Mitglied Konstrukteur, Engineering
Beiträge: 778 Registriert: 18.05.2005 SolidWorks 2020 x64 SP3.0 Dell Precision 5820 Intel Xeon W-2125 4x4GHz NVIDIA Quadro P2000 5GB 32GB RAM 2x Dell U2412M, 24" TFT Windows 10 Enterprise x64 21H1 Microsoft Office 365 ProPlus Microsoft Visual Studio Enterprise 2022
|
erstellt am: 17. Jul. 2014 12:14 <-- editieren / zitieren --> Unities abgeben: Nur für KMassler
Hallo Klaus Mit deinem Code kriegte ich immer eine InvalidCastException (Der Operator = ist für Typ DBNull und Typ Boolean nicht definiert.) Ich habe es darum ein bisschen umgeschrieben... Code: With pc .Name = "Preview" .DefaultCellStyle.NullValue = My.Resources.Gray_Cancel_32x32 .ImageLayout = DataGridViewImageCellLayout.Zoom .DataPropertyName = "Preview" .HeaderText = "Preview" End With
Code: Private Sub DataGridView1_CellFormatting(ByVal sender As Object, ByVal e As System.Windows.Forms.DataGridViewCellFormattingEventArgs) Handles DataGridView1.CellFormatting If Not DataGridView1.Rows(e.RowIndex).IsNewRow Then If DataGridView1.Columns(e.ColumnIndex).Name = "Preview" Then If DataGridView1.Rows(e.RowIndex).Cells("Verheiratet").Value IsNot DBNull.Value Then If CBool(DataGridView1.Rows(e.RowIndex).Cells("Verheiratet").Value) = True Then e.Value = My.Resources.Red_CheckMark_32x32 Else e.Value = My.Resources.Gray_CheckMark_32x32 End If End If End If Else If DataGridView1.Columns(e.ColumnIndex).Name = "Preview" And _ DataGridView1.Rows(e.RowIndex).Cells("Preview").Value IsNot Nothing Then e.Value = My.Resources.Gray_Cancel_32x32 End If End If End Sub
Code: Private Sub DataGridView1_CellEndEdit(ByVal sender As Object, ByVal e As System.Windows.Forms.DataGridViewCellEventArgs) Handles DataGridView1.CellEndEdit Me.Refresh() End Sub
Und hier die beiden Events zu sofortigen aktualisieren http://stackoverflow.com/questions/11843488/datagridview-checkbox-event
Code: Private Sub DataGridView1_CellContentClick(ByVal sender As Object, ByVal e As DataGridViewCellEventArgs) Handles DataGridView1.CellContentClick DataGridView1.CommitEdit (DataGridViewDataErrorContexts.Commit) End Sub
Code: Private Sub DataGridView1_CellValueChanged(ByVal sender As Object, ByVal e As DataGridViewCellEventArgs) Handles DataGridView1.CellValueChanged Me.Refresh() End Sub
Gruss Andreas ------------------ 21 ist nur die halbe Antwort. Eine Antwort auf diesen Beitrag verfassen (mit Zitat/Zitat des Beitrags) IP |
KMassler Ehrenmitglied V.I.P. h.c. CAD Admin + Mädchen für Alles...
Beiträge: 2657 Registriert: 06.11.2000
|
erstellt am: 17. Jul. 2014 16:46 <-- editieren / zitieren --> Unities abgeben:
Danke Andreas! So klappt alles wunderbar, da wäre ich im Leben nicht drauf gekommen. Die Denksportaufgabe ist damit erfolgreich abgeschlossen. Das ist eins meiner Probleme bei VB.Net: Dutzende von Methoden und Ereignisse, die nicht immer selbsterklärend sind und nicht immer das machen, was man sich unter dem Namen vorstellt. Dazu irgendwie doppelte Events wie beispielsweise CellClick und CellMouseClick (nur 1 von vielen Beispielen) - wo ist da der Unterschied? Woher soll man da wissen, welches das richtige Event ist? Da ist es immer wieder schön zu erleben, dass es Leute gibt, die sich in dem Irrgarten zurecht finden Nochmals Danke für die Geduld! Ausnahmsweise hänge ich das Projekt mit an, falls sich noch jemand dran austoben will. Wer weiß, was da noch raus kommt... ------------------ Klaus www.al-ko.com | mein Gästebuch [Diese Nachricht wurde von KMassler am 17. Jul. 2014 editiert.] Eine Antwort auf diesen Beitrag verfassen (mit Zitat/Zitat des Beitrags) IP |
| Anzeige.:
Anzeige: (Infos zum Werbeplatz >>)
|