【问题标题】:Databinding in C# - property names as stringsC# 中的数据绑定 - 作为字符串的属性名称
【发布时间】:2011-09-18 05:38:08
【问题描述】:
阅读this 后,我很确定如何将类的属性绑定到我的UserControl 中的TextBox。我仍然对通过字符串访问属性感到非常不舒服。与该属性的类型或什至存在(在双方)的任何连接都将丢失。
我对这种态度的主要问题是:
- IntelliSense 停止工作 -> 容易出错,不太方便;
- 那里写的任何东西在被调用之前都不会被检查 -> 错误可能会一直被忽视,直到最糟糕的时刻......
是否有其他方法可以创建一个代表一个类的 UserControl,该类连接到该类的实例并保持与它同步? (除了手动使用事件)
【问题讨论】:
标签:
c#
winforms
data-binding
user-controls
【解决方案1】:
(除了手动处理事件)
必须澄清的是,一种和两种方式的数据绑定确实依赖于事件。请阅读How to: Implement Property Change Notification
也就是说,您无需在代码中使用表示属性名称的硬编码字符串即可进行数据绑定。
一种方法是通过自定义属性。您可以在您希望用户控件绑定到的数据模型中装饰某些属性。这样,当DataSource 在您的用户控件中设置时,您可以通过反射在DataSource 对象中搜索自定义Attribute 修饰属性并绑定到它们:
public class MyDataModelObject
{
public int NotBindableProperty { get; }
[MyBindableAttribute]
public string BindableStringProperty
{
get {...}
set {...}
}
}
【解决方案2】:
没有理由强迫您使用字符串,这只是基本的NotifyPropertyChanged 事件机制。例如,Prism Framework 提供了一个简单的包装器,它以 Linq `Expression> 作为参数并使用反射来获取属性名称(但请注意;我曾在一个实例中看到这会导致在属性上使用时出现性能问题在短时间内更新了很多次)。
您可以自己轻松编写这样的包装器,而无需像这样使用整个 Prism 框架:
class NotificationObject : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged = delegate { };
protected virtual void OnPropertyChanged( ProeprtyChangedEventArgs e )
{
PropertyChanged( this, e );
}
protected void RaisePropertyChanged<T>(Expression<Func<T>> propertyExpression )
{
// you'll want to add some error checking here
var name = ((MemberExpression)propertyExpression).Member.Name;
OnPropertyChanged( new PropertyChangedEventArgs( name ) );
}
}
现在你可以通过简单地传入属性来使用它:
class Whatever : NotificationObject
{
private string _foo = String.Empty;
public string Foo
{
get { return _foo ?? String.Empty; }
set
{
if( !_foo.Equals( value ) )
{
_foo = value;
RaisePropertyChanged( this.Foo );
}
}
}
}
现在,如果您重构了 Foo 属性,您也不必担心更新字符串。但这并不能解决另一方面的问题。一个 DependencyProperty 会,但你在内部有字符串问题,IMP 更可取,因为它只是一个地方(在类中)的重复,而不是 n 个外部重复。这并不完美,但有帮助。