Archief - c# .NET data binding probleem

Het archief is een bevroren moment uit een vorige versie van dit forum, met andere regels en andere bazen. Deze posts weerspiegelen op geen enkele manier onze huidige ideeën, waarden of wereldbeelden en zijn op sommige plaatsen gecensureerd wegens ontoelaatbaar. Veel zijn in een andere tijdsgeest gemaakt, al dan niet ironisch - zoals in het ironische subforum Off-Topic - en zouden op dit moment niet meer gepost (mogen) worden. Toch bieden we dit archief nog graag aan als informatiedatabank en naslagwerk. Lees er hier meer over of start een gesprek met anderen.

Ultimus

Legacy Member
hallo,

Ik heb een probleem met databinding. De update past de databank niet aan. Hopelijk kan iemand hier mij helpen, ik ben relatief nieuw en heb een tutorial gevolgd hiervoor, echter zonder resultaat.

tutorial

Code:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Data.OleDb;

namespace NVFinancialTracker
{
    public partial class FormCategory : Form
    {
        string connectString;
        OleDbDataAdapter da;
        DataTable dt;
        BindingSource bs;
        OleDbCommandBuilder cBuilder;

        public FormCategory()
        {
            InitializeComponent();
            connectString = @"Provider=Microsoft.ACE.OLEDB.12.0;Data Source=|DataDirectory|\NVMoneyTracker.accdb";
            da = new OleDbDataAdapter("SELECT * FROM CATEGORY", connectString);
            cBuilder = new OleDbCommandBuilder(da);
            dt = new DataTable();
            da.Fill(dt);
            
            bs = new BindingSource();
            bs.DataSource = dt;
            dataGridView1.DataSource = bs;
        }

        private void button1_Click(object sender, EventArgs e)
        {
            da.Update(dt);
        }

        
    }
}

Prior

Legacy Member
bs.DataSource = dt;

Waarom gebruik je een datatable als het in voorbeeld van de url die je meegeeft een dataset wordt gebruikt?

Als zaken niet lukken is het wel handig om een breakpoint te plaatsen en uw stappen te doorlopen.

Ultimus

Legacy Member
ik heb het met een dataset geprobeerd maar dat leek ook niet te werken.

Vin

Legacy Member
Moet je daarvoor niet ergens je SQL update en/of insert statement meegeven?
Ik weet het niet meer van buiten helaas, en heb even geen tijd om mijn oude cursussen te doorzoeken.

Ultimus

Legacy Member
Code:
            da.UpdateCommand = cBuilder.GetUpdateCommand();
            da.DeleteCommand = cBuilder.GetDeleteCommand();
            da.InsertCommand = cBuilder.GetInsertCommand();
ik heb ook even expliciet de commands overgeladen in data adapter, zonder succes jammer genoeg. Iemand een idee?

Vin

Legacy Member
De update methode van je data-adapter voert wijzigingen die je aangebracht hebt aan de dataset/datatable door naar de database.
Vermits je alle commands correct hebt ingesteld vermoed ik dat het probleem hier niet zal zitten.
Wat ik echter niet zie is op welke plaats je wijzigingen aanbrengt aan de dataset/datatable. Waar je bijvoorbeeld rijen toevoegt, of waarden wijzigt.
Ben je zeker dat je deze wijzigingen niet enkel in je presentatielaag aanbrengt, maar dat deze ook worden doorgevoerd naar de achterliggende dataset/datatable?

Ultimus

Legacy Member
b0red zei:
De update methode van je data-adapter voert wijzigingen die je aangebracht hebt aan de dataset/datatable door naar de database.
Vermits je alle commands correct hebt ingesteld vermoed ik dat het probleem hier niet zal zitten.
Wat ik echter niet zie is op welke plaats je wijzigingen aanbrengt aan de dataset/datatable. Waar je bijvoorbeeld rijen toevoegt, of waarden wijzigt.
Ben je zeker dat je deze wijzigingen niet enkel in je presentatielaag aanbrengt, maar dat deze ook worden doorgevoerd naar de achterliggende dataset/datatable?

wel, je kan wel eens wat op het spoor zijn. als ik de data source van de datagridview koppel aan de binding source dacht ik dat dit voldoende zou zijn. Enig idee wat ik meer moet doen?

TooChé

Legacy Member
via de changed events van uw form, de setters van uw dataklassen aanpassen die uw datasource is? :)

Ultimus

Legacy Member
Code:
private void dataGridView1_changed(object sender, EventArgs e)
        {
            bs.DataSource = dataGridView1.DataSource;
        }

ik heb nu een changed event aangemaakt maar wil nog niet werken :(

Vin

Legacy Member
Not so much...

Die 2 datasources zijn hoogstwaarschijnlijk pointers naar hetzelfde object, dus nu wijs je waarchijnlijk hetzelfde object toe aan bs.DataSource als hetgene dat reeds aanwezig was.

Uit dat EventArgs object ga je moeten afleiden welke rij of cel er in de gridview is aangepast, en met welke waarden.
Vervolgens roep je setters van de datasource op waarbij je de nieuwe waarden invult op de juiste plaats.

[edit] Misschien interessant: het oproepen van die setters zal de aangepaste rijen in de datasource markeren als gewijzigd. Er is een methode van datasource om al deze wijzigingen ongedaan te maken als je dat nog zou wensen. Van zodra je de update methode oproept worden deze wijzigingen pas doorgevoerd naar de database.

Ultimus

Legacy Member
b0red zei:
Not so much...

Die 2 datasources zijn hoogstwaarschijnlijk pointers naar hetzelfde object, dus nu wijs je waarchijnlijk hetzelfde object toe aan bs.DataSource als hetgene dat reeds aanwezig was.

Uit dat EventArgs object ga je moeten afleiden welke rij of cel er in de gridview is aangepast, en met welke waarden.
Vervolgens roep je setters van de datasource op waarbij je de nieuwe waarden invult op de juiste plaats.

[edit] Misschien interessant: het oproepen van die setters zal de aangepaste rijen in de datasource markeren als gewijzigd. Er is een methode van datasource om al deze wijzigingen ongedaan te maken als je dat nog zou wensen. Van zodra je de update methode oproept worden deze wijzigingen pas doorgevoerd naar de database.


Code:
private void dataGridView1_CellValueChanged(object sender, DataGridViewCellValueEventArgs e)

wel ik heb het al aangepast naar bovenstaande. Dit geeft me een x,y en value. Hoe ik hiermee de datasource aanpas is me nog niet geheel duidelijk. De datasource lijkt niet veel methoden te hebben. Kan je me op weg helpen?

hij lijkt het event ook niet te laden, heb even een textbox toegevoegd en daar de waarde van e.Value in geschreven maar die wordt nooit geset na het wijzigen van een cell.

Vin

Legacy Member
Uit de documentatie (msdn) denk ik dat het volgende klopt:
DataGridViewCellValueEventArgs geeft u:
- ColumnIndex
- RowIndex
- Value

DataTable heeft volgende properties:
- Rows: geeft je een collectie van alle rijen terug.
- Columns: geeft je een collectie van alle kolommen terug.

Deze collecties kan je indexeren, en deze geven je dan het gewenste rij of kolomobject terug.
Die rijen en kolommen kan je vervolgens weer indexeren om de gewenste cel te verkrijgen.

Ik vermoed dus dat het volgende zal werken:

Code:
private void dataGridView1_CellValueChanged(object sender, DataGridViewCellValueEventArgs e)
{
    dt.Rows[e.RowIndex][e.ColumnIndex] = e.Value;
}

Om te kijken of je event wel degelijk opgevangen wordt moet je eens een breakpoint zetten op een lijn code in de event handler (de methode ...CellValueChanged).
(Dit doe je door te klikken naast de lijn code, zodat er een rood bolletje voor verschijnt.)
Normaalgezien moet je programma dan stoppen en keer je terug naar de editor, naar de lijn code die je hebt aangeduid. Gebeurt dit niet, dan wordt je event inderdaad niet aangeroepen.
Maar tenzij ik iets over het hoofd zie heb je dit wel correct geimplementeerd.

[edit] Ik heb zo'n vermoeden dat je je form met de designer ontworpen hebt. Ik denk dat je dan op je datatable moet klikken in de designer, en dat je daar in het properties venstertje de juiste eventhandler moet opgeven bij het CellValueChanged event. Not sure though, niet zoveel ervaring met die forms designer.

Ultimus

Legacy Member
b0red zei:
[edit] Ik heb zo'n vermoeden dat je je form met de designer ontworpen hebt. Ik denk dat je dan op je datatable moet klikken in de designer, en dat je daar in het properties venstertje de juiste eventhandler moet opgeven bij het CellValueChanged event. Not sure though, niet zoveel ervaring met die forms designer.

wel het lijkt op de goede weg te zitten. Echter is het CellValueChanged event niet te combineren met DataGridViewCellValueEventHandler, deze werkt enkel met de DataGridViewCellEventHandler. Wat is het juiste event waarbij ik toch de cell value handler kan gebruiken? of een andere handler waar ook de waarden uit te halen zijn?

edit:
Uiteindelijk een andere approach gevonden, CellEndEdit event en dan via eventargs de juiste cell uit datagridview copieren naar datatable. Echter, na een kleine controle, is gebleken dat dt reeds de aangepaste waarde bevat. De bindingsource doet zijn werk lijkt me, echter kan ik niet verklaren waarom het updaten van de databank niet lukt?! een idee?

Ultimus

Legacy Member
Ondertussen ben ik dus gekomen tot het onderstaande. Maar nog steeds geen update in de databank. Iemand een idee?:doh:

Code:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Data.OleDb;

namespace NVFinancialTracker
{
    public partial class FormCategory : Form
    {
        string connectString;
        OleDbDataAdapter da;
        DataTable dt;
        BindingSource bs;
        OleDbCommandBuilder cBuilder;

        public FormCategory()
        {
            InitializeComponent();
            connectString = @"Provider=Microsoft.ACE.OLEDB.12.0;Data Source=|DataDirectory|\NVMoneyTracker.accdb";
            da = new OleDbDataAdapter("SELECT * FROM CATEGORY", connectString);
            cBuilder = new OleDbCommandBuilder(da);
            da.UpdateCommand = cBuilder.GetUpdateCommand();
            da.DeleteCommand = cBuilder.GetDeleteCommand();
            da.InsertCommand = cBuilder.GetInsertCommand();
            //MessageBox.Show(da.UpdateCommand.CommandText.ToString());
            dt = new DataTable();
            da.Fill(dt);

            
            
            bs = new BindingSource();
            bs.DataSource = dt;
            dataGridView1.DataSource = bs;
        }

        private void dataGridView1_CellEndEdit(object sender, DataGridViewCellEventArgs e)
        {

            da.Update(dt);
        }

        private void button1_Click(object sender, EventArgs e)
        {
            da.Update(dt);
        }

        
    }
}

Ultimus

Legacy Member
Tot mijn grote spijt moet ik bekennen dat bovenste code weldegelijk blijkt te werken. Het probleem hier was eerder van menselijke aard *ahum*, als men de verkeerde database checkt op veranderingen, dan durft het al eens lijken alsof de code zijn werk niet doet. *mental note: Database wordt mee in de debug folder gecopieerd* :doh:
Het archief is een bevroren moment uit een vorige versie van dit forum, met andere regels en andere bazen. Deze posts weerspiegelen op geen enkele manier onze huidige ideeën, waarden of wereldbeelden en zijn op sommige plaatsen gecensureerd wegens ontoelaatbaar. Veel zijn in een andere tijdsgeest gemaakt, al dan niet ironisch - zoals in het ironische subforum Off-Topic - en zouden op dit moment niet meer gepost (mogen) worden. Toch bieden we dit archief nog graag aan als informatiedatabank en naslagwerk. Lees er hier meer over of start een gesprek met anderen.
Terug
Bovenaan