• Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 1312
  • Last Modified:

BindingNavigator problems: column cannot be null

I have an Oracle database, which I access through a typed dataset.
I have some bound fields and a BindingNavigator on a form (created with the drag/drop functions in VS2005).

When I run the project and click the 'Add New' button on the navigator, it adds one to the internal list and allows editing.
If I click the 'Add New' button again, it throws an exception at the Application.Run(Form1) level, saying one of my columns cannot be null.

I have Googled the problem and come up with other examples: http://groups.google.com/group/microsoft.public.dotnet.framework.windowsforms.databinding/browse_thread/thread/83602e5caf7cc4a8/ff35910ef8f7a755?lnk=st&q=%2B%22BindingNavigator%22+%2B%22add+button%22&rnum=1#ff35910ef8f7a755

I have also tried to add ErrorProvider handling but find that the suggested event is not fired:
http://msdn2.microsoft.com/en-us/ms171930.aspx

I think it has to do with the EndEdit() method of the BindingSource, but I can find no resolution.

How can I trap this error efficiently?

J
0
jimbobmcgee
Asked:
jimbobmcgee
  • 3
  • 2
  • 2
1 Solution
 
MuhammadAdilCommented:
Hello Dear

there is any column which is not nullable at DB and ur entering null data in that field
Or may be u r not binding this feild with any control and u insert data it remain null

0
 
jimbobmcgeeAuthor Commented:
I understand that I can't enter a null, where my column is not nullable, but the exception is raised in such a way that it seems untrappable.

As an example, I can do the following in the Click event handler for the BindingNavigator's 'Save' button, like so:

    try
    {
        myBindSource.EndEdit();
        myTableAdapter.Update(myDataTable);
        MessageBox.Show("Update successful");
    }
    catch (Exception ex)
    {
        MessageBox.Show(string.Format("Update failed - {0}", ex.Message));
    }

but, it seems stupid to try:

    try
    {
        Application.Run(new myForm);
    }
    catch (Exception ex)
    {
        MessageBox.Show(string.Format("General failure - {0}", ex.Message));
    }

because, by this point, the form has already been destroyed.

Is this some kind of oversight by Microsoft in its develoment of the BindingNavigator object, or am I handling the whole thing wrong?

J.
0
 
jimbobmcgeeAuthor Commented:
So far, I am preventing the second click, by extending the BindingNavigator as follows:

    public class ExtendedBindingNavigator : BindingNavigator
    {
        public ExtendedBindingNavigator()
        {
            this.ItemClicked += new ToolStripItemClickedEventHandler(ExtendedBindingNavigator_ItemClicked);
        }

        private void ExtendedBindingNavigator_ItemClicked(object sender, ToolStripItemClickedEventArgs e)
        {
            if (sender == this.AddNewItem && this.BindingSource != null)
                this.BindingSource.CancelEdit();
        }
    }

Seems a bit of a hack, though...

J.
0
Concerto's Cloud Advisory Services

Want to avoid the missteps to gaining all the benefits of the cloud? Learn more about the different assessment options from our Cloud Advisory team.

 
MuhammadAdilCommented:
Hello Dear

This code is not giving clear understanding. Describe in detail.
0
 
sumixCommented:
Hello,

 The behavior of BindingSource object is indeed strange in some situations and this object does things that it shouldn't do. Even if you don't use a BindingNavigator, if you have a new added row with some fields with constraint error (null values or something else), and you try to change the position in the bindingsource(a new add, or navigate backward etc) you get a constraint error and after that a CancelEdit is done. This makes the new line to disappear, which shouldn't happen!!! You should be allowed to correct the error, this is an ugly bug.

Tha bad thing is that in the scenario you described, the error cannot be traped and the applications ends.
A workaround I could think of until now is to add a handler for ItemClicked event of bindingnavigator and try an EndEdit in your own try/catch block:

        private void bindingNavigator1_ItemClicked(object sender, ToolStripItemClickedEventArgs e)
        {
            if (e.ClickedItem.Equals(bindingNavigator1.AddNewItem))
            {
                try
                { bindingSource1.EndEdit(); }
                catch (Exception err)
                {
                    MessageBox.Show(err.ToString());
                    bindingSource1.CancelEdit();
                }
            }
        }
 
Or, more general, you can create a new class derived from BindingNavigator and override OnItemClicked method:
class MyBindingNavigator :BindingNavigator
    {
        public MyBindingNavigator(System.ComponentModel.IContainer c):base(c)
        {}
       
        protected override void OnItemClicked(ToolStripItemClickedEventArgs e)
        {
           if (e.ClickedItem.Equals(AddNewItem))
          {
            try
            {
                BindingSource.EndEdit();
                base.OnItemClicked(e);
            }
            catch (Exception err)
            {
                MessageBox.Show("Nasty error: " + err.ToString());
                BindingSource.CancelEdit();
            }
          }
        }
    }
0
 
jimbobmcgeeAuthor Commented:
Thanks, sumix, that confirms both what I thought and what I am doing.  

As such, the I feel next question is fairly obvious:  What is the best way to insert new records, when the Null constraint is fired by the dataset?  My INSERT SQL statement provides default values for certain null entries (incremented sequences, etc) and, as such, I do not want the end user to be able to edit these fields.  These fields are, therefore, databound to Labels.

I was under the impression that, when you call MyTableAdapter.Update(MyDataTable) the TableAdapter object would decide for itself whether to use the INSERT statement or the UPDATE one, dependant on whether the row already existed, but this seems not to be the case.  The UPDATE SQL is always called, which fails the null constraints (both at the dataset and at the database, when MyDataset.EnableConstraints = false)

What is the most efficient way to perform my insertion when 'Save' is clicked?

J.
0
 
sumixCommented:

When you click an a AddNew button a new row is added in the datatable and its RowState is 'Added'. When you call Update method of the tableadapter, depending on the RowState property, the corresponding Insert/Update/Delete command is executed for every row - this is true.
You should set default values for columns in the DataTable where is the case (dataTable1.Columns["column"].DefaultValue property) or you may set EnforceContraints property of the dataset to false before starting editing the table (this will stop constraints checking).
 So, in Save click you could only call Update method of the tableadapter.
0

Featured Post

Free Tool: Subnet Calculator

The subnet calculator helps you design networks by taking an IP address and network mask and returning information such as network, broadcast address, and host range.

One of a set of tools we're offering as a way of saying thank you for being a part of the community.

  • 3
  • 2
  • 2
Tackle projects and never again get stuck behind a technical roadblock.
Join Now