I have a DataGridView bound to a bindingsource which is bound to a List
. The user clicks a row that goes to a form with textboxes, etc. The textboxes a
I aren't sure if it was available when the question was asked but I use the grid_CurrentCellDirtyStateChanged; event
first make Sure you set DataSourceUpdateMode.OnPropertyChanged
txrFirstName.DataBindings.Add("Text", bindingSource1, "FirstName", false,DataSourceUpdateMode.OnPropertyChanged);
then add add this code to your movenext click event
if (((DataRowView)bindingSource1.Current).IsNew)
{
MessageBox.Show("Current Row IsNew");
}
if (((DataRowView)bindingSource1.CurrencyManager.Current).Row.HasVersion(DataRowVersion.Proposed))
{
MessageBox.Show("Current Row Modified");
DialogResult dialogResult = MessageBox.Show("Current Row Modified", "Some Title", MessageBoxButtons.YesNo);
if (dialogResult == DialogResult.Yes)
{
//do something
((DataRowView)bindingSource1.CurrencyManager.Current).Row.AcceptChanges();
}
else if (dialogResult == DialogResult.No)
{
//do something else
((DataRowView)bindingSource1.CurrencyManager.Current).Row.RejectChanges();
}
}
else {
bindingSource1.MoveNext();
}
I made this function now. You can use like:
if (changedOrNew(myBindingSource)){
// Do something!
}
public bool changedOrNew(BindingSource bs){
EntityObject obj = (EntityObject)bs.Current;
if (obj==null)
return false;
return (obj.EntityState == EntityState.Detached ||
obj.EntityState == EntityState.Added ||
obj.EntityState == EntityState.Modified);
}
What I always do is to capture the individual "changed" events of the controls. In the below example I used a tabcontrol in this example. The Try/Catch is a dirty solution for not having to deal with all kinds of exceptions ;-)
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
'
' some code
'
BindingNavigatorSaveItem.Enabled = False
For Each tabctl As Control In Me.TabControl1.Controls
For Each ctl As Control In tabctl.Controls
Try
If ctl.GetType Is GetType(TextBox) Then
AddHandler DirectCast(ctl, TextBox).TextChanged, AddressOf GenDataChanged
ElseIf ctl.GetType Is GetType(NumericUpDown) Then
AddHandler DirectCast(ctl, NumericUpDown).ValueChanged, AddressOf GenDataChanged
ElseIf ctl.GetType Is GetType(ComboBox) Then
AddHandler DirectCast(ctl, ComboBox).SelectedValueChanged, AddressOf GenDataChanged
ElseIf ctl.GetType Is GetType(CheckBox) Then
AddHandler DirectCast(ctl, CheckBox).CheckStateChanged, AddressOf GenDataChanged
End If
Catch ex As Exception
End Try
Next
Next
End Sub
Private Sub GenDataChanged(sender As System.Object, e As System.EventArgs)
BindingNavigatorSaveItem.Enabled = True
End Sub
If your bindingsource uses a datatable you can do this :
public bool HasChanges()
{
bool Result = false;
myBindingSource.EndEdit();
Result = ((DataTable)myBindingSource.DataSource).GetChanges(DataRowState.Modified) != null;
return Result;
}
I know this is an old post but here is an Extended BindingSource with IsDirtyFlag - you can adapt it how you would like - I pulled this code from another posting somewhere on the net years ago - made some very minor changes I think it was originally in VB - I converted to C# ..
using System.ComponentModel.Design;
using System.Windows.Forms;
using System.ComponentModel;
using System.Data;
using System;
public class BindingSourceExIsDirty : System.Windows.Forms.BindingSource, INotifyPropertyChanged
{
#region "DECLARATIONS AND PROPERTIES"
private string _displayMember;
private DataTable _dataTable;
private DataSet _dataSet;
private BindingSource _parentBindingSource;
private System.Windows.Forms.Form _form;
private System.Windows.Forms.Control _usercontrol;
private bool _isCurrentDirtyFlag = false;
public bool IsCurrentDirty {
get { return _isCurrentDirtyFlag; }
set {
if (_isCurrentDirtyFlag != value) {
_isCurrentDirtyFlag = value;
this.OnPropertyChanged(value.ToString());
//call the event when flag is set
if (value == true) {
OnCurrentIsDirty(new EventArgs());
}
}
}
}
private string _objectSource;
public string ObjectSource {
get { return _objectSource; }
set {
_objectSource = value;
this.OnPropertyChanged(value);
}
}
private bool _autoSaveFlag;
public bool AutoSave {
get { return _autoSaveFlag; }
set {
_autoSaveFlag = value;
this.OnPropertyChanged(value.ToString());
}
}
#endregion
#region "EVENTS"
//Current Is Dirty Event
public event CurrentIsDirtyEventHandler CurrentIsDirty;
// Delegate declaration.
public delegate void CurrentIsDirtyEventHandler(object sender, EventArgs e);
protected virtual void OnCurrentIsDirty(EventArgs e)
{
if (CurrentIsDirty != null) {
CurrentIsDirty(this, e);
}
}
//PropertyChanged Event
// public event PropertyChangedEventHandler INotifyPropertyChanged.PropertyChanged;
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged(string info)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(info));
}
}
#endregion
#region "METHODS"
private void _BindingComplete(System.Object sender, System.Windows.Forms.BindingCompleteEventArgs e)
{
if (e.BindingCompleteContext == BindingCompleteContext.DataSourceUpdate) {
if (e.BindingCompleteState == BindingCompleteState.Success & !e.Binding.Control.BindingContext.IsReadOnly) {
//Make sure the data source value is refreshed (fixes problem mousing off control)
e.Binding.ReadValue();
//if not focused then not a user edit.
if (!e.Binding.Control.Focused)
return;
//check for the lookup type of combobox that changes position instead of value
if (e.Binding.Control as ComboBox != null) {
//if the combo box has the same data member table as the binding source, ignore it
if (((ComboBox)e.Binding.Control).DataSource != null) {
if (((ComboBox)e.Binding.Control).DataSource as BindingSource != null) {
if (((BindingSource)((ComboBox)e.Binding.Control).DataSource).DataMember == (this.DataMember)) {
return;
}
}
}
}
IsCurrentDirty = true;
//set the dirty flag because data was changed
}
}
}
private void _DataSourceChanged(System.Object sender, System.EventArgs e)
{
_parentBindingSource = null;
if (this.DataSource == null) {
_dataSet = null;
} else {
//get a reference to the dataset
BindingSource bsTest = this;
Type dsType = bsTest.DataSource.GetType();
//try to cast the data source as a binding source
while ((bsTest.DataSource as BindingSource != null)) {
//set the parent binding source reference
if (_parentBindingSource == null)
_parentBindingSource = bsTest;
//if cast was successful, walk up the chain until dataset is reached
bsTest = (BindingSource)bsTest.DataSource;
}
//since it is no longer a binding source, it must be a dataset or something else
if (bsTest.DataSource as DataSet == null) {
//Cast as dataset did not work
if (dsType.IsClass == false) {
throw new ApplicationException("Invalid Binding Source ");
} else {
_dataSet = null;
}
} else {
_dataSet = (DataSet)bsTest.DataSource;
}
//is there a data member - find the datatable
if (!string.IsNullOrEmpty(this.DataMember)) {
_DataMemberChanged(sender, e);
}
//CType(value.GetService(GetType(IDesignerHost)), IDesignerHost)
if (_form == null)
GetFormInstance();
if (_usercontrol == null)
GetUserControlInstance();
}
}
private void _DataMemberChanged(System.Object sender, System.EventArgs e)
{
if (string.IsNullOrEmpty(this.DataMember) | _dataSet == null) {
_dataTable = null;
} else {
//check to see if the Data Member is the name of a table in the dataset
if (_dataSet.Tables(this.DataMember) == null) {
//it must be a relationship instead of a table
System.Data.DataRelation rel = _dataSet.Relations(this.DataMember);
if ((rel != null)) {
_dataTable = rel.ChildTable;
} else {
throw new ApplicationException("Invalid Data Member");
}
} else {
_dataTable = _dataSet.Tables(this.DataMember);
}
}
}
public override System.ComponentModel.ISite Site {
get { return base.Site; }
set {
//runs at design time to initiate ContainerControl
base.Site = value;
if (value == null)
return;
// Requests an IDesignerHost service using Component.Site.GetService()
IDesignerHost service = (IDesignerHost)value.GetService(typeof(IDesignerHost));
if (service == null)
return;
if ((service.RootComponent as Form != null)) {
_form = (Form)service.RootComponent;
} else if ((service.RootComponent as UserControl != null)) {
_usercontrol = (UserControl)service.RootComponent;
}
}
}
public System.Windows.Forms.Form GetFormInstance()
{
if (_form == null & this.CurrencyManager.Bindings.Count > 0) {
_form = this.CurrencyManager.Bindings[0].Control.FindForm();
}
return _form;
}
/// <summary>
/// Returns the First Instance of the specified User Control
/// </summary>
/// <returns>System.Windows.Forms.Control</returns>
public System.Windows.Forms.Control GetUserControlInstance()
{
if (_usercontrol == null & this.CurrencyManager.Bindings.Count > 0) {
System.Windows.Forms.Control[] _uControls = null;
_uControls = this.CurrencyManager.Bindings[0].Control.FindForm().Controls.Find(this.Site.Name.ToString(), true);
_usercontrol = _uControls[0];
}
return _usercontrol;
}
public BindingSourceExIsDirty()
{
DataMemberChanged += _DataMemberChanged;
DataSourceChanged += _DataSourceChanged;
BindingComplete += _BindingComplete;
}
// PositionChanged
private override void _PositionChanged(object sender, EventArgs e)
{
if (IsCurrentDirty) {
// IsAutoSavingEvent
if (AutoSave | MessageBox.Show(_msg, "Confirm Save", MessageBoxButtons.YesNo) == DialogResult.Yes) {
try {
//cast table as ITableUpdate to get the Update method
// CType(_dataTable, ITableUpdate).Update()
} catch (Exception ex) {
MessageBox.Show(ex, "Position Changed Error");
// - needs to raise an event
}
} else {
this.CancelEdit();
_dataTable.RejectChanges();
}
IsCurrentDirty = false;
}
base(e);
}
#endregion
}