Toon posts:

[VB.NET] Uitdunnen van DataGridView d.m.v. een button.

Pagina: 1
Acties:

Onderwerpen


  • BETA911
  • Registratie: Januari 2007
  • Laatst online: 01-02 10:54
Hello guys,

Zit met een vervelend probleem weer.

Het probleem zit hem erin dat ik niet de juiste werkwijze weet noch kan vinden hoe ik korter tot een oplossing kan komen van dit probleem.
Het ligt er aan dat ik niet weet hoe ik eraan moet beginnen, noch kan ik geen info vinden (of die me helpt) hoe dit op te lossen of in de juiste weg te duwen.

Het probleem is als volgt:
Ik heb een DataGridView (dgvMain) die gevuld is met data uit een .db3 bestand aan de hand van een connectie, dataadapter, dataset... Nu wil ik dat de gebruiker de keuze heeft om deze DataGridView te kunnen uitdunnen door heel eenvoudig een selectie te maken en op een knop te drukken.
Normaliter zou dan het volgende moeten gebeuren:


Maar ik krijg dit niet voor elkaar op geen enkele wijze.

Ik heb geprobeerd:
- Nieuwe DataGridView aangemaakt (dgvNew)
- De geselecteerde cellen toe te wijzen (dgvNew.Datasource = dgvMain.SelectedCells)
- dgvMain te verbergen, dgvNew te laten zien.

Hier staat dan vanalles in, maar niet hetgeen er in zou moeten staan.

Ik zie genoeg info op het net om celwaardes uit te lezen en er vanalles mee te doen, of hele rijen. Dit kan wel als het zou moeten (m.a.w. zou me wel lukken) maar dit moet ik niet hebben.
Ik had al gedacht om met rijen te werken en dan gewoon iets te doen van .Rows.Add(...) maar dat kan niet omdat de gebruiker ook met CTRL+LMK aparte cellen kan selecteren (variërend bereik dus).

Iemand die weet hoe ik dit zou kunnen oplossen?

  • NickThissen
  • Registratie: November 2007
  • Laatst online: 23-05 20:03
Je rijen zouden instanties van een bepaalde klasse moeten zijn, waarbij die klasse een property voor elke kolom heeft (dus Timestamp, SerialNumber, InvertedNumber, etc). Je laadt dan een collectie van instanties van die klasse en geeft die collectie aan als de DataSource. Ik weet niet welke naam voor jou klasse van toepassing is, dus noem het maar even 'Class1'.

Als je gebruiker dan de selectie wilt uitdunnen neem je gewoon een nieuw lijstje met Class1 instanties, die je uit de geselecteerde rijen kunt halen mbv DataGridView.SelectedRows[i].DataBoundItem (ik dacht dat dat de naam was), die je daarna weer als DataSource opgeeft.

[Voor 9% gewijzigd door NickThissen op 21-05-2011 23:36]

Mijn iRacing profiel


90710

Gebruik je .NET 3.0 of nieuwer.. gebruik dan LINQ ;)

Visual Basic .NET:
1
2
Dim selectedData = (From di In DataGridView1.SelectedRows.Cast(Of DataGridViewRow)()
                           Select di.DataBoundItem).Cast(Of Class1)().ToArray()


Waarbij Class1 de klasse is waar je data in staat en DataGridView1 je datagridview.

De selectedData array kan je nu aan een DataSource van een andere (of dezelfde) DataGridview doorgeven.

Ik heb het even wat verder uitgewerkt :p
Visual Basic .NET:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
    Protected Overrides Sub OnLoad(e As System.EventArgs)
        MyBase.OnLoad(e)

        Dim personen() As Persoon

        Dim sander As New Persoon With {.GeboorteDatum = New Date(1984, 3, 21), .Geslacht = Geslacht.Man, .Naam = "Sander"}
        Dim julia As New Persoon With {.GeboorteDatum = New Date(1985, 4, 10), .Geslacht = Geslacht.Vrouw, .Naam = "Julia"}
        Dim rick As New Persoon With {.GeboorteDatum = New Date(1980, 2, 20), .Geslacht = Geslacht.Man, .Naam = "Rick"}

        personen = {sander, julia, rick}

        DataGridView1.DataSource = personen

    End Sub

    Private Sub Button1_Click(sender As System.Object, e As System.EventArgs) Handles Button1.Click
        Dim selectedData = (From di In DataGridView1.SelectedRows.Cast(Of DataGridViewRow)()
                           Select di.DataBoundItem).Cast(Of Persoon)().ToArray()

        DataGridView1.DataSource = selectedData
    End Sub


Dit is ongeveer wat je bedoelt, toch?

Als je dan ook nog niet-geselecteerde kolommen wilt verbergen moet je nog iets met SelectedColumns doen. Maar als je dat niet wil kan je er ook voor kiezen om SelectionMode op FullRowSelect te zetten.

Let op dat rijen die niet volledig geselecteerd zijn niet in de SelectedRows Collectie komen ;) Maar ook dáár kan je omheen komen door de selectedData LINQ te veranderen in:
Visual Basic .NET:
1
2
        Dim selectedData = (From sc In DataGridView1.SelectedCells.Cast(Of DataGridViewCell)()
                            Select sc.OwningRow.DataBoundItem).Distinct().Cast(Of Persoon)().ToArray()

Vergeet vooral de Distinct() niet, anders heb je een heleboel dubbele items.

Edit: Ik zie net dat dit de volgorde van items omkeert. Hier kan je aan ontkomen door .Reverse() na .Distinct() uit te voeren. Dat keert de array weer om.

Je kan meerdere leuke dingen met LINQ doen, maar daarvoor verwijs ik je naar MSDN.
MSDN: 101 LINQ Samples
Dit zijn dan wel C# voorbeelden, maar ze werken vrijwel identiek in VB.

[Voor 95% gewijzigd door 90710 op 22-05-2011 00:42]


Acties:
  • 0Henk 'm!

  • BETA911
  • Registratie: Januari 2007
  • Laatst online: 01-02 10:54
NickThissen schreef op zaterdag 21 mei 2011 @ 23:34:
Je rijen zouden instanties van een bepaalde klasse moeten zijn, waarbij die klasse een property voor elke kolom heeft (dus Timestamp, SerialNumber, InvertedNumber, etc). Je laadt dan een collectie van instanties van die klasse en geeft die collectie aan als de DataSource. Ik weet niet welke naam voor jou klasse van toepassing is, dus noem het maar even 'Class1'.

Als je gebruiker dan de selectie wilt uitdunnen neem je gewoon een nieuw lijstje met Class1 instanties, die je uit de geselecteerde rijen kunt halen mbv DataGridView.SelectedRows[i].DataBoundItem (ik dacht dat dat de naam was), die je daarna weer als DataSource opgeeft.
Eerlijk gezegd snap ik niet concreet wat je hier bedoeld :) . Heb je misschien een voorbeeld?
90710 schreef op zaterdag 21 mei 2011 @ 23:50:
Gebruik je .NET 3.0 of nieuwer.. gebruik dan LINQ ;)

Visual Basic .NET:
1
'...


Waarbij Class1 de klasse is waar je data in staat en DataGridView1 je datagridview.

De selectedData array kan je nu aan een DataSource van een andere (of dezelfde) DataGridview doorgeven.

Ik heb het even wat verder uitgewerkt :p
Visual Basic .NET:
1
    '...


Dit is ongeveer wat je bedoelt, toch?

Als je dan ook nog niet-geselecteerde kolommen wilt verbergen moet je nog iets met SelectedColumns doen. Maar als je dat niet wil kan je er ook voor kiezen om SelectionMode op FullRowSelect te zetten.

Let op dat rijen die niet volledig geselecteerd zijn niet in de SelectedRows Collectie komen ;) Maar ook dáár kan je omheen komen door de selectedData LINQ te veranderen in:
Visual Basic .NET:
1
 '...

Vergeet vooral de Distinct() niet, anders heb je een heleboel dubbele items.

Edit: Ik zie net dat dit de volgorde van items omkeert. Hier kan je aan ontkomen door .Reverse() na .Distinct() uit te voeren. Dat keert de array weer om.

Je kan meerdere leuke dingen met LINQ doen, maar daarvoor verwijs ik je naar MSDN.
MSDN: 101 LINQ Samples
Dit zijn dan wel C# voorbeelden, maar ze werken vrijwel identiek in VB.
Ik gebruik .NET 3.5.
Heb je voorbeeld even copy-paste gedaan en namen aangepast:
Visual Basic:
1
2
3
4
    Private Sub btnSelectedCells_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnSelectedCells.Click
        Dim selectedData = (From sc In dgvMain.SelectedCells.Cast(Of DataGridViewCell)() Select sc.OwningRow.DataBoundItem).Distinct().Cast(Of frmMain)().ToArray()
        dgvMain.DataSource = selectedData
    End Sub


Maar krijg dan deze error:


Ik heb het LINQ gebeuren nog niet bekeken, dat ga ik nu doen.

EDIT:

Heb het even snel bekeken en het is niet meer of minder dan soort SQL.
In elk geval, heb de code aangepast naar:
Visual Basic:
1
2
3
4
5
6
Dim selectedData = (From sc In dgvMain.SelectedCells.Cast(Of DataGridViewCell)()
                            Select sc.OwningRow.DataBoundItem).Distinct().ToList()
        Dim bsNew As New BindingSource
        bsNew.DataSource = selectedData
        dgvMain.DataSource = Nothing
        dgvMain.DataSource = bsNew


En nu werkt het wel (zo goed als). Ik weet niet als de extra BindingSource nodig is (waarschijnlijk niet). Maar hetgeen hij nu doet is elke rij waarin een cell geselecteerd is, laat hij zien. Kortom, het werkt nu per rij. Ik ben ook aan het overwegen om dat zo misschien te laten. Want, je zal gekke resultaten krijgen mocht je zoiets als dit filteren:

[Voor 27% gewijzigd door BETA911 op 22-05-2011 14:37]


Acties:
  • 0Henk 'm!

90710

Je kan het beste .ToList() vervangen door .ToArray(), je hebt niet een nieuwe list nodig (extra geheugen verbruik)
En de BindingSource is ook niet nodig.

Ook "dgvMain.DataSource = Nothing" Is overbodig.

Het beste kan je nu van de DatagridView de SelectionMode property op FullRowSelect zetten zodat de gebruiker niet een bepaalde cell kan selecteren. (gebruik dan SelectedRows ipv SelectedCells, ook kan je dan Distinct() achterwegen laten)

Tot slot wil ik je nog even inlichten over je eerste foutmelding, je probeert nu de data in de rij naar je form te casten, wat natuurlijk niet gaat ;) In mijn voorbeeld is Persoon een klasse met gegevens over een bepaald persoon, zoals in de OnLoad aangegeven is.

Visual Basic .NET:
1
2
3
4
5
6
7
8
9
10
11
12
Public Class Persoon

    Public Property Naam As String
    Public Property GeboorteDatum As Date
    Public Property Geslacht As Geslacht

End Class

Public Enum Geslacht As Integer
    Man = 0
    Vrouw = 1
End Enum

(Extra informatie: klasse Persoon en Enum Geslacht)

En ja, LINQ is inderdaad een soort van SQL :+ Alleen werk je met LINQ met objecten en met SQL met data in een database.
LINQ = Language Integrated Query, SQL = Structured Query Language. Met beide maak je queries, alleen is LINQ een onderdeel van een (programmeer) taal. SQL is een taal op zich.

LINQ is echt een godsgeschenk als je veel met data in je software werkt. :) En dan ben ik niet eens gelovig :p

[Voor 64% gewijzigd door 90710 op 22-05-2011 22:54]


Acties:
  • 0Henk 'm!

  • BETA911
  • Registratie: Januari 2007
  • Laatst online: 01-02 10:54
90710 schreef op zondag 22 mei 2011 @ 22:38:
Je kan het beste .ToList() vervangen door .ToArray(), je hebt niet een nieuwe list nodig (extra geheugen verbruik)
En de BindingSource is ook niet nodig.

Ook "dgvMain.DataSource = Nothing" Is overbodig.

Het beste kan je nu van de DatagridView de SelectionMode property op FullRowSelect zetten zodat de gebruiker niet een bepaalde cell kan selecteren. (gebruik dan SelectedRows ipv SelectedCells, ook kan je dan Distinct() achterwegen laten)

Tot slot wil ik je nog even inlichten over je eerste foutmelding, je probeert nu de data in de rij naar je form te casten, wat natuurlijk niet gaat ;) In mijn voorbeeld is Persoon een klasse met gegevens over een bepaald persoon, zoals in de OnLoad aangegeven is.

Visual Basic .NET:
1
2
3
4
5
6
7
8
9
10
11
12
Public Class Persoon

    Public Property Naam As String
    Public Property GeboorteDatum As Date
    Public Property Geslacht As Geslacht

End Class

Public Enum Geslacht As Integer
    Man = 0
    Vrouw = 1
End Enum

(Extra informatie: klasse Persoon en Enum Geslacht)

En ja, LINQ is inderdaad een soort van SQL :+ Alleen werk je met LINQ met objecten en met SQL met data in een database.
LINQ = Language Integrated Query, SQL = Structured Query Language. Met beide maak je queries, alleen is LINQ een onderdeel van een (programmeer) taal. SQL is een taal op zich.

LINQ is echt een godsgeschenk als je veel met data in je software werkt. :) En dan ben ik niet eens gelovig :p
Oké, dat maakt het allemaal duidelijk!
Inderdaad, ik heb bij de DatagridView de SelectionMode property op FullRowSelect gezet. Werkt perfect nu.

EDIT:
Als ik .ToArray() gebruik dan blijft men DataGridView leeg na het klikken op de button. Maar bij .ToList() werkt het wel :) .

[Voor 4% gewijzigd door BETA911 op 23-05-2011 10:51]

Pagina: 1


Tweakers maakt gebruik van cookies

Tweakers plaatst functionele en analytische cookies voor het functioneren van de website en het verbeteren van de website-ervaring. Deze cookies zijn noodzakelijk. Om op Tweakers relevantere advertenties te tonen en om ingesloten content van derden te tonen (bijvoorbeeld video's), vragen we je toestemming. Via ingesloten content kunnen derde partijen diensten leveren en verbeteren, bezoekersstatistieken bijhouden, gepersonaliseerde content tonen, gerichte advertenties tonen en gebruikersprofielen opbouwen. Hiervoor worden apparaatgegevens, IP-adres, geolocatie en surfgedrag vastgelegd.

Meer informatie vind je in ons cookiebeleid.

Sluiten

Toestemming beheren

Hieronder kun je per doeleinde of partij toestemming geven of intrekken. Meer informatie vind je in ons cookiebeleid.

Functioneel en analytisch

Deze cookies zijn noodzakelijk voor het functioneren van de website en het verbeteren van de website-ervaring. Klik op het informatie-icoon voor meer informatie. Meer details

janee

    Relevantere advertenties

    Dit beperkt het aantal keer dat dezelfde advertentie getoond wordt (frequency capping) en maakt het mogelijk om binnen Tweakers contextuele advertenties te tonen op basis van pagina's die je hebt bezocht. Meer details

    Tweakers genereert een willekeurige unieke code als identifier. Deze data wordt niet gedeeld met adverteerders of andere derde partijen en je kunt niet buiten Tweakers gevolgd worden. Indien je bent ingelogd, wordt deze identifier gekoppeld aan je account. Indien je niet bent ingelogd, wordt deze identifier gekoppeld aan je sessie die maximaal 4 maanden actief blijft. Je kunt deze toestemming te allen tijde intrekken.

    Ingesloten content van derden

    Deze cookies kunnen door derde partijen geplaatst worden via ingesloten content. Klik op het informatie-icoon voor meer informatie over de verwerkingsdoeleinden. Meer details

    janee