Reputation: 309
class Class1
{
public string val {get;set;}
}
Class1 cl;
private void Form1_Load(object sender, EventArgs e)
{
cl = new Class1();
textBox1.DataBindings.Add("Text",cl,"val",false,DataSourceUpdateMode.OnPropertyChanged,);
textBox2.DataBindings.Add("Text", cl, "val", false, DataSourceUpdateMode.OnPropertyChanged);
}
private void button1_Click(object sender, EventArgs e)
{
cl.val += "11";
}
I change value in textBox1, at textBox2 value changes immediatly too.
If I click button, bindings value cl.val changed from code, but both textBox value stay unchanged.
How to refresh data on textbox form if cl.val change from code?
PS: if after row
cl.val += "11"; - add
textBox1.Text = cl.val;
then value refresh at both textBoxs
why is that?
Upvotes: 2
Views: 9452
Reputation: 205539
In order to make data binding work when data source property is changed by a code, the data source (Class1
in your case) must provide some sort of a property change notification. The possible choices are events called PropertyNameChanged
where PropertyName
is the name of the property for which the change notification applies, or more general approach is to implement INotifyPropertyChanged Interface.
Here is an example using the second approach. Since the C# auto properties cannot be used anymore, people usually create a base class to reduce repetitive boilerplate code needed like this
public abstract class BindableObject : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
var handler = PropertyChanged;
if (handler != null)
handler(this, new PropertyChangedEventArgs(propertyName));
}
protected static bool SetProperty<T>(ref T field, T value, [CallerMemberName] string propertyName = null)
{
if (EqualityComparer<T>.Default.Equals(field, value)) return false;
field = value;
OnPropertyChanged(propertyName);
return true;
}
}
and then use it as follows
class Class1 : BindableObject
{
private string _val;
public string val
{
get { return _val; }
set { SetProperty(ref _val, value); }
}
}
Once you do this, everything will work as expected.
If as you said your class is auto generated by EF, then you need to create a wrapper class (usually referred as ViewModel) to be used for UI data binding. In general, DTOs, Entities etc. classes are not for direct use in the UI.
Update While all the above is the right way to go, for the sake of completeness, here is a quick and dirty approach.
Helper function:
public static class DataBindingUtils
{
public static void RefreshBindings(this BindingContext context, object dataSource)
{
foreach (var binding in context[dataSource].Bindings.Cast<Binding>())
binding.ReadValue();
}
}
Sample usage:
private void button1_Click(object sender, EventArgs e)
{
cl.val += "11";
BindingContext.RefreshBindings(cl);
}
Upvotes: 3
Reputation: 7703
Try this:
cl.val+="11";
textBox1.ResetBindings();
textBox2.ResetBindings();
Update
The fact is that when you change the class value, you must notify the UI that the underlying data has changed, so you must implement INotifyPropertyChanged in your class. Define your class Class1 like this and try it:
class Class1:INotifyPropertyChanged
{
private string _val;
public string val
{
get
{
return this._val;
}
set
{
if (this._val != value)
{
this._val = value;
NotifyPropertyChanged("");
}
}
}
public event PropertyChangedEventHandler PropertyChanged;
private void NotifyPropertyChanged(String propertyName)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
}
Update 2
As Ivan and me has explained, the way to do it is implementing INotifyPropertyChanged. But if you want a dirty way of doing it,you could clear databindings and add them again, something like:
cl.val += "11";
foreach (Control c in this.Controls)
{
if (c is TextBox)
{
c.DataBindings.Clear();
c.DataBindings.Add("Text", cl, "val", false, DataSourceUpdateMode.OnPropertyChanged);
}
}
Upvotes: 0