This project is read-only.

Updating bound database after cell change

Sep 27, 2010 at 9:33 PM

I am still struggling with how to automatically force a save of a bound dataset back to a database, after a cell is changed (see previous post of September 20, I am opening a new discussion in hopes of getting a response).

The example of frmsample26 just triggers a message about the changed cell, with no apparent capability to update the entire dataset.   Example 51 uses delegates to actually get back to the grid.  Is the delegate approach the proper one?  If so, as I am continually confused on delegate syntax, can somebody point me in the proper direction?

Thanks and I apologize for the related post.

 

Dick Males

Cincinnati, OH, USA

Sep 30, 2010 at 12:02 PM

Hi Dick

Updating a database is an out of scope topic for this project.

>with no apparent capability to update the entire dataset. 

What do you mean exactly by "update dataset"? As far as i see, SourceGrid is showing data from dataset, and as soon as cell value is changed, a corresponding row in dataset is also updated.

 

Delegates is a simple callback or observer pattern in .Net world. These are used extensively throughout the project. I am not sure what to tell you more about those :)

Sep 30, 2010 at 9:52 PM

Thank you for your reply.   I have solved my problem, posting here for the record.

I agree that how to update a database is out of scope, but I know how to do it (see code below).  I have also been able to implement the delegate-based method that I need to cause the overriden OnValueChanged handler to call the needed function to write back to the database .  What I wanted to do was to trigger this callback function when I am leaving a cell after the contents have been changed, much as MS Access works to immediately commit changes in the user-editable grid back to the database.

The question is when exactly, on changing a cell in a datagrid, is the bound dataset changed.   A dataset has an associated  HasChanges method (http://msdn.microsoft.com/en-us/library/system.data.dataset.haschanges.aspx) that indicates when the dataset has been modified.   Apparently, the Update method of the adapter will only update (i.e. write back to the database) if this is set to true.   So the question is, when does this happen when modifying a cell in a SourceGrid?   On making the change but remaining in the cell?  On leaving the cell?  I have done a fair amount of experimenting, and it appears that the dataset is marked as changed only after leaving the cell.  Consequently, what seems to work for my purposes is to provide a cell controller that overrides the OnFocusLeft event, and then to call the SaveToDatabase delegate function, which will internally test as to whether the dataset has been changed before writing.  Consequently, just moving from cell to cell will trigger the SaveToDatabase function, but if the dataset has not been changed, then there will not be any write back to the database.

The SaveToDatabase Function looks like this:

  private void SaveToDatabase() // for use with delegate function
        { OdbcCommandBuilder cb = new OdbcCommandBuilder(adapter);
            adapter.InsertCommand = cb.GetInsertCommand();
            adapter.UpdateCommand = cb.GetUpdateCommand();
                     
            if (dataset.HasChanges()) // test here to see if database needs updating
            {
              //  MessageBox.Show("in SaveToDatabase DatasetHasChanges= " + dataset.HasChanges().ToString());
                try
                {
                    adapter.Update(dataset);
                }
                catch (Exception ex)
                {
                    MessageBox.Show(ex.ToString());
                }
            }
        }

The revised controller is:

     public class FocusLeftEvent : SourceGrid.Cells.Controllers.ControllerBase
        {
            public delegate void SaveDelegate();
            private SourceGridForm mFrm;
            public SaveDelegate m_SaveDelegate = null;
            public FocusLeftEvent(SourceGridForm frm) // pass in the calling form to the constructor
        {
            mFrm=frm;
        }
          
          
            public override void OnFocusLeft(SourceGrid.CellContext sender, EventArgs e)//OnValueChanged(SourceGrid.CellContext sender, EventArgs e)
            {
                base.OnFocusLeft(sender, e);
                mFrm.Invoke(m_SaveDelegate, null); // invoke the save function            
            }
        }

and this is associated with the datagrid as:

  FocusLeftEvent focusLeftController = new FocusLeftEvent(this);          
  dataGrid1.Controller.AddController(focusLeftController);

  focusLeftController.m_SaveDelegate = new FocusLeftEvent.SaveDelegate(this.SaveToDatabase);

 

There are a few other lines of code associated with getting the delegate going, if anybody is interested in this I will be happy to provide a more complete set of code.

Thanks for the response and all of your efforts on SourceGrid.  I believe that there are a fair number of us out here who very much enjoy using the powerful and flexible SourceGrid control, in the context of database access.

 

Dick Males

Cincinnati, OH, USA