why GetChanges returns something (when bound to a property) even if there are no changes on datatable?
-
03-07-2019 - |
Question
Bound GetChanges
always returns something when bound to a UserControl
's property (even on a simple one)
I have made a UserControl
, for some reason unbeknownst to me, when I bound a DataColumn
to my control's property the dataSet1.GetChanges()
always return something, even the column bound to my control was not changed.
What's the possible cause why GetChanges
always return something?
Here's a simple snippet to reproduce the binding/GetChanges problem:
using System;
using System.Data;
using System.Windows.Forms;
namespace BindingBug
{
public partial class Form1 : Form
{
DataSet _ds = new DataSet();
void GetData()
{
var t = new DataTable
{
TableName = "beatles",
Columns =
{
{"lastname", typeof(string)},
{"firstname", typeof(string)},
{"middlename", typeof(string)}
}
};
t.Rows.Add("Lennon", "John", "Winston");
t.Rows.Add("McCartney", "James", "Paul");
_ds.Tables.Add(t);
}
public string Hey { set; get; }
public Form1()
{
InitializeComponent();
var tLastname = new TextBox { Top = 100 };
var tFirstname = new TextBox { Top = 130 };
this.Controls.Add(tLastname);
this.Controls.Add(tFirstname);
GetData();
tLastname.DataBindings.Add("Text", _ds.Tables["beatles"], "lastname");
tFirstname.DataBindings.Add("Text", _ds.Tables["beatles"], "firstname");
// if the following line is commented 2nd:Has Changes == false
this.DataBindings.Add("Hey", _ds.Tables["beatles"], "middlename");
_ds.AcceptChanges();
MessageBox.Show("1st:Has Changes = " + _ds.HasChanges().ToString());
var bDetectChanges = new Button { Top = 160, Text = "Detect Changes" };
bDetectChanges.Click +=
delegate
{
this.BindingContext[_ds.Tables["beatles"]].EndCurrentEdit();
MessageBox.Show("2nd:Has Changes = " + (_ds.GetChanges() != null).ToString());
};
this.Controls.Add(bDetectChanges);
}
}
} //namespace BindingBug
Solution
i was able to solve the problem today, the key thing is to make the BindingContext's EndCurrentEdit aware if the value really changed. for this, we must implement System.ComponentModel.INotifypropertychanged on our control. i just saw the solution from here: http://msdn.microsoft.com/en-us/library/system.componentmodel.inotifypropertychanged.propertychanged.aspx
hope this can help others implementing their own controls which flag wrong change status on GetChanges()
public partial class Form1 : Form, System.ComponentModel.INotifyPropertyChanged
{
//----------- implements INotifyPropertyChanged -----------
// wish C# has this VB.NET's syntactic sugar
public event System.ComponentModel.PropertyChangedEventHandler PropertyChanged; // implements INotifyPropertyChanged.PropertyChanged
//----------- start of Form1 ----------
DataSet _ds = new DataSet();
void NotifyPropertyChanged(string propertyName)
{
if (PropertyChanged != null)
PropertyChanged(this, new System.ComponentModel.PropertyChangedEventArgs(propertyName));
}
void GetData()
{
var t = new DataTable
{
TableName = "beatles",
Columns =
{
{"lastname", typeof(string)},
{"firstname", typeof(string)},
{"middlename", typeof(string)}
}
};
t.Rows.Add("Lennon", "John", "Winston");
t.Rows.Add("McCartney", "James", "Paul");
t.Columns["middlename"].DefaultValue = "";
_ds.Tables.Add(t);
}
string _hey = "";
public string Hey
{
set
{
if (value != _hey)
{
_hey = value;
NotifyPropertyChanged("Hey");
}
}
get
{
return _hey;
}
}
public Form1()
{
InitializeComponent();
var tLastname = new TextBox { Top = 100 };
var tFirstname = new TextBox { Top = 130 };
this.Controls.Add(tLastname);
this.Controls.Add(tFirstname);
GetData();
tLastname.DataBindings.Add("Text", _ds.Tables["beatles"], "lastname");
tFirstname.DataBindings.Add("Text", _ds.Tables["beatles"], "firstname");
this.DataBindings.Add("Hey", _ds.Tables["beatles"], "middlename");
_ds.AcceptChanges();
MessageBox.Show("1st:Has Changes = " + _ds.HasChanges().ToString());
var bDetectChanges = new Button { Top = 160, Text = "Detect Changes" };
bDetectChanges.Click +=
delegate
{
this.BindingContext[_ds.Tables["beatles"]].EndCurrentEdit();
MessageBox.Show("2nd:Has Changes = " + (_ds.GetChanges() != null).ToString());
};
this.Controls.Add(bDetectChanges);
}
}