DataGridView, Uložení hodnoty buňky do DataSource ihned po ukončení editace buňky   otázka

VB.NET, ADO.NET, WinForms, Databáze

Přeji pěkný den. Dobří lidé, prosím...

Mám DataGridView1 připojený na DataTable. Existuje nějaká metoda/vlastnost, pomocí níž lze ukládat hodnotu buňky do DataSource ihned po ukončení editace/validace buňky ? Tedy i v případě, že nedojde k opuštění řádku ?

Zkoušel jsem vše, i ve VirtualMode, ale prostě NE. DataGridView ukládá do DataSource až po opuštění řádku.

Zdá se mi logické, že by taková vlastnost/metoda měla existovat - DataGridView se mi jeví jako mocný nástroj. Věřím také, že s tím už pár lidí bojovalo, i proto se ptám zde. Nebo to prostě musím udělat ručně např. v eventu CellValidated ? V tom případě prosím o příklad, jak to udělat čistě. (Následně se bude provádět aktualizace v databázi pomocí SqlDataAdapter-u.)

Díky Moc, Dalibor

nahlásit spamnahlásit spam 0 odpovědětodpovědět

Ještě doplním kód, omlouvám se, zkoušel jsem vše možné a tak nějak nemohl vybrat, co pro ilustraci zde uvést. Proto jsem to raději popsal slovně. Když to tedy zjednoduším... Tohle funguje, ale až v okamžiku, kdy uživatel opustí editovaný řádek:

    Private Sub dataGridView1_CellValidating(ByVal sender As Object, ByVal e As DataGridViewCellValidatingEventArgs) Handles DataGridView1.CellValidating

        If DataGridView1.IsCurrentCellDirty Then zmena = True

        'Ošetření vstupů
        '
        '

    End Sub

    Private Sub DataGridView1_RowValidated(ByVal sender As Object, ByVal e As DataGridViewCellEventArgs) Handles DataGridView1.RowValidated

        If zmena Then sqlAdapter.Update(tabule) : zmena = False ': MessageBox.Show("SQLUpdated")

    End Sub

A tohle nefunguje - do databáze se změna uloží až při následující editaci, protože při té první ještě není změna promítnuta ani v DataTable. A já bych právě potřeboval tu změnu promítnout již zde (nebo existuje-li ještě nějaký, tak při posledním eventu po editaci buňky). Navíc, do SQL synchronizovat jen, došlo-li skutečně ke změně.

   Private Sub dataGridView1_CellValidating(ByVal sender As Object, ByVal e As DataGridViewCellValidatingEventArgs) Handles DataGridView1.CellValidating

        If DataGridView1.IsCurrentCellDirty Then zmena = True

        'Ošetření vstupů
        '
        '

    End Sub


    Private Sub DataGridView1_CellValidated(ByVal sender As System.Object, ByVal e As System.Windows.Forms.DataGridViewCellEventArgs) Handles DataGridView1.CellValidated

        If zmena Then sqlAdapter.Update(tabule) : zmena = False ': MessageBox.Show("SQLUpdated")

    End Sub

Nedal by se využít např. event CellValuePushed ? Jak to udělat čistě (aby se to např. neukládalo dvakrát, uložím-li to do DataTable ručně v tomto eventu. A také, uložím-li to ručně, označí se spolehlivě záznam v DataTable pro následující SQL Update ?) a co vše obnáší virtuální režim DataGridView ? Co vše je třeba ošetřovat ručně při aktivovaném virtuálním režimu ? A nebo se v zásadě nic nemění, nebudu-li virtuální režim na nic jiného potřebovat ?

Díky Moc, Dalibor

nahlásit spamnahlásit spam 0 odpovědětodpovědět

Střílím od boku, ale nestačilo by v události CurrentCellDirtyStateChanged zavolat .CommitEdit ???

nahlásit spamnahlásit spam 0 odpovědětodpovědět

Díky, ale bohužel ne. CommitEdit neukládá do DataSource a CurrentCellDirtyStateChanged nastává ještě před CellValidating.

Ještě mě napadlo v eventu CellValidated vyvolat událost RowValidated nebo RowLeave. Ale metody OnRowValidated a OnRowLeave jsou protected. Chápu, že jsou asi chráněné z nějakého důvodu a pravděpodobně to bude k ničemu. Ale přesto, poradili byste prosím, jak se taková chráněná metoda volá ? A jestli byste to vůbec doporučovali ?

Ještě mě napadá jako nejzažší řešení v eventu CellValidated změnit aktuální buňku - opustit řádek - a zase zpět. Ale to je asi dost prasárna.

Tomášové, Václave, Ondřeji, nepomohli byste prosím ? Jsem velmi vděčný za vbnet.cz a Děkuji Vám za něj. Již jen pouhým prohlížením mi pomohl vyřešit několik problémů. Když něco googlim a vbnet.cz je ve výsledcích, vždy mi srdce poskočí ;-). K dotazu ve fóru jsem se odhodlal poprvé (a hned na to podruhé ohledně té češtiny při Copy - Paste ;-) ).

Nebo, neodkázali byste mě někdo na nějaký dostupný materiál, kde by byly události DataGridView popsány chronologicky - tedy ke kterým událostem a v jakém pořadí dochází při běžných akcích, jako např. ukončení editace buňky nebo opuštění řádku. Případně, jaké metody jsou volány.

Případně prosím poraďte, jak vlastně správně do DataTable ukládat ručně, aby se nerozhodil ten status pro následnou synchronizaci s SQL pomocí SqlAdapter-u.

nahlásit spamnahlásit spam 1 / 1 odpovědětodpovědět

Tak jsem to napsal ručně, asi pořádná prasárna. Zdrojovou tabulku jsem prostě obešel, ať si s ní DataGrid dělá co chce, když se nedá donutit, aby ukládal každou buňku.

Funguje zdá se perfektně. Ještě ale nevím, na jaké problémy narazím při synchronizaci změn v databázi do DataSource. Konečným cílem je dosáhnout toho, aby se změna každého pole projevila u všech klientů okamžitě. Zjednodušeně (bez ošetření vstupů) to mám takhle:

Private Sub dataGridView1_CellValidating(ByVal sender As Object, ByVal e As DataGridViewCellValidatingEventArgs) Handles DataGridView1.CellValidating

    If DataGridView1.IsCurrentCellDirty Then zmena = True

End Sub

Private Sub DataGridView1_CellValidated(ByVal sender As System.Object, ByVal e As System.Windows.Forms.DataGridViewCellEventArgs) Handles DataGridView1.CellValidated

    If zmena Then
        'sqlAdapter.Update(tabule)  'Původní automatický Update nahražuje následující kód.
        Dim pole As String = ""
        Select Case e.ColumnIndex
            Case 1 : pole = "Edit1"
            Case 6 : pole = "Edit2"
            Case 7 : pole = "Edit3"
            Case 8 : pole = "Edit4"
            Case 9 : pole = "Edit5"
            Case 10 : pole = "Edit6"
            Case 11 : pole = "Edit7"
            Case Else : MessageBox.Show("POZOR! Neznámý index sloupce pro uložení do databáze. Hodnota nebyla uložena.") : zmena = False : Exit Sub
        End Select

        myCommand.CommandType = CommandType.Text
        If IsDBNull(DataGridView1.CurrentCell.Value) Then
            myCommand.CommandText = "Update Tabule set " & pole & " = null where CisloZaznamu = '" & DataGridView1(0, e.RowIndex).Value & "'"
        Else
            myCommand.CommandText = "Update Tabule set " & pole & " = '" & DataGridView1.CurrentCell.Value & "' where CisloZaznamu = '" & DataGridView1(0, e.RowIndex).Value & "'"
        End If

        sqlConnect.Open()
        myCommand.ExecuteScalar()
        sqlConnect.Close()
        zmena = False
    End If

End Sub

nahlásit spamnahlásit spam 1 / 1 odpovědětodpovědět

Tak to funguje, i se zpětnou aktualizací v reálném čase, kterou z důvodu minimalizace datových toků a nároků na systémové zdroje řeším s pomocí Triggeru v databázi, který tvoří ChangeList tabulku. Podle ní potom aktualizuji DataTable metodou LoadDataRow.

Vše nasvědčuje tomu, že aktualizace přímo v databázi (příklad kódu výše) je nakonec poměrně vhodné řešení, protože samotné DataTable nepodporuje ukládání jednotlivých buněk. Záznam by se musel načíst, změnit buňku a znovu uložit, což je podle mého názoru horší, zejména při multithread řešení vzniká navíc několik nebezpečných situací, které by se musely ošetřovat.

nahlásit spamnahlásit spam 1 / 1 odpovědětodpovědět
                       
Nadpis:
Antispam: Komu se občas házejí perly?
Příspěvek bude publikován pod identitou   anonym.
  • Administrátoři si vyhrazují právo komentáře upravovat či mazat bez udání důvodu.
    Mazány budou zejména komentáře obsahující vulgarity nebo porušující pravidla publikování.
  • Pokud nejste zaregistrováni, Vaše IP adresa bude zveřejněna. Pokud s tímto nesouhlasíte, příspěvek neodesílejte.

přihlásit pomocí externího účtu

přihlásit pomocí jména a hesla

Uživatel:
Heslo:

zapomenuté heslo

 

založit nový uživatelský účet

zaregistrujte se

 
zavřít

Nahlásit spam

Opravdu chcete tento příspěvek nahlásit pro porušování pravidel fóra?

Nahlásit Zrušit

Chyba

zavřít

feedback