自从从WPF上学了点皮毛之后,开始也把上面的东西往WinForm上用,比如说双向绑定,重点是INotifyPropertyChanged的使用(原谅我这个一直搞web的人吧,貌似INotifyPropertyChanged在.net 2.0的时候已经有了,双向绑定的好处我就不说了)
先定义了一个类作为控件的数据源
public class BindParamModel : INotifyPropertyChanged
{
private string _n;
public event PropertyChangedEventHandler PropertyChanged;
public string N
{
set
{
if (_n != value)
{
_n = value;
OnPropertyChanged("N");
}
}
get { return _n; }
}
..........
protected virtual void OnPropertyChanged(string propertyName)
{
var handler = PropertyChanged;
if (handler != null)
handler(this, new PropertyChangedEventArgs(propertyName));
}
}
上面的类继承INotifyPropertyChanged 接口,作为控件的数据源.
然后给一个TextBox 绑定这个数据源
control.DataBindings.Add("Text", BindParamModel, "N");
这样就把BindParamModel的N属性与TextBox的Text作了绑定,那么问题来了
这个
control.DataBindings.Add("Text", BindParamModel, "N");
我放在一个循环里面,DataBindings这个对象没有类似Contain这样的方法判断"Text"属性已被绑定过,再Add就会出错 我经过调试,发现DataBindings下有一个属性叫List(里面保存着控件上绑定的所有对象,Binding),不过它是一个private的非公开对象,只能通过反射得到它了,于是我有了下面的处理方法
private static bool ControlHasBindProperty(Control control,string propertyName)
{
var listProperty =
control.DataBindings.GetType()
.GetProperties(BindingFlags.NonPublic | BindingFlags.Instance)
.First(property => property.Name == "List");
var bindList = (ArrayList) listProperty.GetValue(control.DataBindings, null);
if (bindList.OfType<Binding>().FirstOrDefault(prop => prop.PropertyName == propertyName) != null)
return true;
return false;
}
下面调用上面的函数先检查一下这个属性有没有被绑定过,接下来的事件就容易了
var hasBind = ControlHasBindProperty(textBox, "Text");
if (!hasBind)
textBox.DataBindings.Add("Text", BindParamModel, "N");