none
Creating a new GUID with BindingNavigatorAddNewItem_Click(). RRS feed

  • Question

  • I have a form that contains a BindingNavigator.  The ID for this form and SQL Server database table used to be of type int, but I have recently changed it to a GUID.  I used the DataSet Designer from .NET Framework 2.0 to build a strongly-typed DataSet.  I rebuilt the DataSet after changing the ID from an int to a GUID.  The updated form will run and iterate through the records okay.  I am having a problem with creating new records.

    When the form had an int ID, the ID would increment by -1 each time a new record was started.  Now, clicking the BindingNavigator's add new item button starts with a blank GUID.  Is there a way to force the DataSet/BindingSource/BindingNavigator to create a new GUID ID whenever the BindingNavigator's add new item button is clicked?

    I need this to happen at the DataSet / BindingSource level because this form has multiple DataGridViews (many-to-many tables) to which this form's ID is part of a composite primary key.  The DataGridViews use the GUID ID in the BindingSource to filter the many-to-many records to only those associated with the form's GUID.  Since the form's GUID does not exist when a new BindingNavigator record is started, attempting to select records in the DataGridViews produces the error, "An exception occured. Column 'testGUID' does not allow nulls."  The GUID needs to exist at the BindingSource level when a new record is commenced so that the DataGridViews know which GUID to which they are associating in their many-to-many tables.  Thanks!

    • Edited by Devin Howe Friday, September 10, 2010 8:19 PM
    Friday, September 3, 2010 10:15 PM

All replies

  • You can override OnTableNewRow in the DataSet designer code-behind:

    namespace WindowsFormsApplication1 { 
      public partial class TestDataSet {
        partial class DataTable1DataTable
        {
          protected override void OnTableNewRow(System.Data.DataTableNewRowEventArgs e)
          {
            e.Row["TestGuid"] = System.Guid.NewGuid();
            base.OnTableNewRow(e);
          }
        }
      }
    }
    
    
    Saturday, September 4, 2010 1:51 PM
  • I adapted the code for my DataSet and am receiving errors that there is "no suitable method found to override" and "'object' does not contain a definition for 'OnTableNewRow'".

    I searched the TestDataSet.xsd, TestDataSet.Designer.cs, TestDataSet.xsc, and TestDataSet.xss files and was not able to find a method called OnTableNewRow.  Is this method always created by the DataSet Designer for DataTables?

    Tuesday, September 7, 2010 4:36 PM
  • Double-click on the table/cylinder icon in the upper-left of the table in the DataSet designer.  This will present you with two partial class declarations.  Put the protected override... code inside.

     

     

    Tuesday, September 7, 2010 10:31 PM
  • Thanks, I was able to get the code to compile and execute.  Unfortunately, breakpoints show that the method is not called when I press the AddNewItem button on the BindingNavigator.  The new record's GUID textbox loads up blank and the M-to-M DataGridViews throw exceptions that they're not associated with an ID as well.
    Wednesday, September 8, 2010 4:01 PM
  • I created a small Windows Forms Application to test.  The database is as follows:

    create table "Application_Personnel" ( 
    	"ApplicationId" uniqueidentifier not null,
    	"PersonnelId" uniqueidentifier not null) 
    
    go
    
    alter table "Application_Personnel"
    	add constraint "Application_Personnel_PK" primary key ("ApplicationId", "PersonnelId") 
    
    go
    
    create table "Personnel" ( 
    	"PersonnelId" uniqueidentifier ROWGUIDCOL default (newid()) not null,
    	"FirstName" varchar(50) not null,
    	"LastName" varchar(50) not null) 
    go
    
    alter table "Personnel"
    	add constraint "Personnel_PK" primary key ("PersonnelId") 
    
    go
    
    create table "Application" ( 
    	"ApplicationId" uniqueidentifier ROWGUIDCOL default (newid()) not null,
    	"Description" varchar(50) null) 
    
    go
    
    alter table "Application"
    	add constraint "Application_PK" primary key ("ApplicationId") 
    
    go
    
    alter table "Application_Personnel"
    	add constraint "Application_Application_Personnel_FK1" foreign key (
    		"ApplicationId")
    	 references "Application" (
    		"ApplicationId") on update no action on delete cascade 
    
    go
    
    alter table "Application_Personnel"
    	add constraint "Personnel_Application_Personnel_FK1" foreign key (
    		"PersonnelId")
    	 references "Personnel" (
    		"PersonnelId") on update no action on delete cascade 
    
    go
    

    I created a new Windows Forms Application and used the DataSource designer to create a GuidTestDataSet.  I expanded the Application entity and changed the entity's dropdown from DataGridView to Details.  I dragged the Application entity onto my form and received Application Id and Description labels and textboxes.  I then dragged the Application_Personnel DataGridView (listed under the Application entity) onto my form so that I filter the DataGridView to only show Personnel for the current Application record.

    I double clicked on the bindingNavigatorAddNewItem button and added the following code:

      private void bindingNavigatorAddNewItem_Click(object sender, EventArgs e)
      {
       applicationIdTextBox.Text = Guid.NewGuid().ToString();  
      }
    

    Clicking on the AddNewItem button now gives me a new GUID in the applicationIdTextBox but it does not populate the ApplicationId column in the DataGridView when I tab down and start a new DataGridView row.  However, if I edit an existing application record and tab through the DataGridView, it will populate the ApplicationId column for each new DataGridView row.

    It seems that I need to set the new Application record's ApplicationId at the BindingSource so that the DataGridView will have access to it.  I attempted to do so with the following code:

      private void bindingNavigatorAddNewItem_Click(object sender, EventArgs e)
      {
       ((GuidTestDataSet.ApplicationRow)applicationBindingSource.Current).ApplicationId = Guid.NewGuid();   
      }
    

    However, I receive a runtime error when I click on the AddNewItem button stating: Unable to cast object of type 'System.Data.DataRowView' to type 'ApplicationRow'.  I tried casting the object to a DataRowView type but am not sure how to get it back into the BindingSource.Current object.

    Will modifying the BindingSource.Current object make the DataGridView populate the ApplicationId for a new row?  Is there a way to set a property of the BindingSource.Current object?  Thanks!

    Friday, September 10, 2010 7:27 PM
  • It appears calling BindingSource.EndEdit() will make the ApplicationId automatically populate in a new DataGridView row as long as ApplicationId is the only required field.  Unfortunately, I have other required fields.

      private void bindingNavigatorAddNewItem_Click(object sender, EventArgs e)
      {
       applicationIdTextBox.Text = Guid.NewGuid().ToString();
       applicationBindingSource.EndEdit();
      }
    

     

    Friday, September 10, 2010 8:53 PM
  • > I double clicked on the bindingNavigatorAddNewItem button and added the following code:

    I agree, doing this in the UI is a reasonable way to go.

    > does not populate the ApplicationId column

    Windows Forms Data Binding has some quirks.  I didn't test this but I think WriteValue will help right after you set Text:

    applicationIdTextBox.Text = Guid.NewGuid().ToString(); 
    applicationIdTextBox.DataBindings["Text"].WriteValue();
    
    

    (Note that there is also a ReadValue for the opposite situation where you have the data in the DataRow but it has not appeared in the UI for some reason.)

    Friday, September 10, 2010 11:34 PM
  • The WriteValue() method appears to update the GUID on the BindingSource.Current object for the new parent record but it will still not populate the ApplicationId column in the DataGridView for new child records.  I wonder what wires up the DataGridView on existing parent records to fill in the ApplicationId column (PK) for new child records and why doesn't it behave the same way for a new parent record's DataGridView?
    Monday, September 13, 2010 6:12 PM