When you click on BindingNavigator buttons, the exception is not thrown from your code, it's thrown in framework classes, so you cannot set a breakpoint. You need to avoid the exception, or if you want to handle it in Application.ThreadException, you need to check stack trace.
This post answers two questions:
- How to avoid exception when clicking on navigation buttons or add/remove/save buttons?
- How to know if ToolStripButton was involved in the actions which resulted in throwing an exception?
1 - How to avoid exception when clicking on navigation buttons or add/remove/save buttons?
Disable constraints in the form load. Then in the Save button click, enable them, handle the exceptions (if necessary) and disable them again:
private async void Form1_Load(object sender, EventArgs e)
{
dataSet1.EnforceConstraints = false;
}
private void dataTable1BindingNavigatorSaveItem_Click(object sender, EventArgs e)
{
try
{
dataSet1.EnforceConstraints = true;
}
catch (Exception ex)
{
//process errors if necessary
}
dataSet1.EnforceConstraints = false;
}

Any other option to avoid the exception?
Yes, as another option to avoid the error, you can just remove the default functionalities from buttons; for example select the binding navigator, and in properties find the AddNewItem and select (none)
as its value. Then double click on the button to handle its click event and handle it like this:
private void bindingNavigatorAddNewItem_Click(object sender, EventArgs e)
{
try
{
myBindingNavigator.BindingSource.AddNew();
}
catch (Exception)
{
//process the error, for example show a message
}
}
2 - How to know if ToolStripButton was involved in the actions which resulted in throwing an exception?
This exception is not thrown from your code, but thrown in framework classes. Looking into the e.Exception.StackTrace
of the exception that you have handled in Application.ThreadException
, you see all the necessary details including class names and method names:
at System.Data.DataColumn.CheckNullable(DataRow row)
at System.Data.DataTable.RaiseRowChanging(DataRowChangeEventArgs args, DataRow eRow, DataRowAction eAction, Boolean fireEvent)
at System.Data.DataTable.SetNewRecordWorker(DataRow row, Int32 proposedRecord, DataRowAction action, Boolean isInMerge, Boolean suppressEnsurePropertyChanged, Int32 position, Boolean fireEvent, Exception& deferredException)
at System.Data.DataTable.InsertRow(DataRow row, Int64 proposedID, Int32 pos, Boolean fireEvent)
at System.Data.DataView.FinishAddNew(Boolean success)
at System.Data.DataRowView.EndEdit()
at System.Windows.Forms.CurrencyManager.EndCurrentEdit()
at System.Windows.Forms.BindingSource.EndEdit()
at System.Windows.Forms.BindingSource.AddNew()
at System.Windows.Forms.BindingNavigator.OnAddNew(Object sender, EventArgs e)
at System.Windows.Forms.ToolStripItem.RaiseEvent(Object key, EventArgs e)
at System.Windows.Forms.ToolStripButton.OnClick(EventArgs e)
at System.Windows.Forms.ToolStripItem.HandleClick(EventArgs e)
at System.Windows.Forms.ToolStripItem.HandleMouseUp(MouseEventArgs e)
at System.Windows.Forms.ToolStripItem.FireEventInteractive(EventArgs e, ToolStripItemEventType met)
at System.Windows.Forms.ToolStripItem.FireEvent(EventArgs e, ToolStripItemEventType met)
at System.Windows.Forms.ToolStrip.OnMouseUp(MouseEventArgs mea)
at System.Windows.Forms.Control.WmMouseUp(Message& m, MouseButtons button, Int32 clicks)
at System.Windows.Forms.Control.WndProc(Message& m)
at System.Windows.Forms.ScrollableControl.WndProc(Message& m)
at System.Windows.Forms.ToolStrip.WndProc(Message& m)
at System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m)
at System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m)
at System.Windows.Forms.NativeWindow.Callback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)
You can also get the stack frames yourself:
var frames = new StackTrace(e.Exception, true).GetFrames();
And then you can search between the frames, for example by checking:
Where(x => x.GetMethod().DeclaringType == typeof(ToolStripButton))