正如您在WPF
应用程序中所知,如果要将特定类的某些属性绑定到控件的属性,则必须实现该类的INotifyPropertyChanged
接口。
现在考虑我们有许多没有实现INotifyPropertyChanged
的普通类。这个例子非常简单:
public class User : ModelBase
{
public int Id { get; set; }
public string UserName { get; set; }
public string Password { get; set; }
// ...
}
例如我想将UserName
绑定到TextBox
,所以我应该编写另一个新的User
类来实现INotifyPropertyChanged
,如下所示:
public class User : INotifyPropertyChanged
{
public string Password { get {return _Password}}
set {_Password=value;OnPropertyChanged("Password");}
// ... Id and UserName properties are implemented like Password too.
public event PropertyChangedEventHandler PropertyChanged;
private void OnPropertyChanged(string propertyName)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
// ...
}
现在我的问题是,你知道是否有任何机制或技巧来简化它?
考虑到我们有超过100个模型,可能会被更改。
我在想一种方法,比如使用泛型类来做(编辑):
public class BindableClass<NormalClass> { ...adding ability to bind instructions using reflection... }
NormalClass NormalInstance = new NormalClass();
// simple class, does not implemented INotifyPropertyChanged
// so it doesn't support binding.
BindableClass<NormalClass> BindableInstance = new BindableClass<NormalClass>();
// Implemented INotifyPropertyChanged
// so it supports binding.
当然,我不确定这是不是好方法!澄清我的问题只是一个想法。
请不要告诉我没有办法或不可能!有数百种型号!!!
感谢。
答案 0 :(得分:1)
如果您无法修改源类,则可以调查Unity新版本中的“行为注入”功能。 “行为注入”功能允许您将类连接到BEHAVE,就好像它从INotifyPropertyChanged继承而不修改类本身。
昨天here有一个非常相似的主题,它提供了让你开始的链接。 Unity团队甚至为您提供了在POCO类上创建INotifyPropertyChanged的注入器的源代码。我已经使用它并且可以证明它有效。有一个性能损失,但如果您不想修改源类但仍然喜欢WPF绑定的功能,那么这是游戏的一部分。
答案 1 :(得分:0)
将InNotifyPropertyChanged实现移动到基类,让视图模型继承该基类。
基类
public class BaseNotify
{
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged(string propertyName)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
}
您的View Model类
public class User : BaseNotify
{
private string userName;
public string UserName
{
get { return userName; }
set
{
userName = value;
OnPropertyChanged("UserName");
}
}
}
答案 2 :(得分:0)
我目前没有正在使用的IDE,但我认为这可行(我不确定泛型)
帮助
public class Bindable<T>: RealProxy, INotifyPropertyChanged
{
private T obj;
private Bindable(T obj)
: base(typeof(T))
{
this.obj = obj;
}
// not sure if this compiles,
// make it a property in that case and the ctor public
public static T BuildProxy(T obj)
{
return (T) new Bindable<T>(obj).GetTransparentProxy();
}
public override IMessage Invoke(IMessage msg)
{
var meth = msg.Properties["__MethodName"].ToString();
var bf = BindingFlags.Public | BindingFlags.Instance ;
if (meth.StartsWith("set_"))
{
meth = meth.Substring(4);
bf |= BindingFlags.SetProperty;
}
if (meth.StartsWith("get_"))
{
bf |= BindingFlags.GetProperty;
// get the value...
meth = meth.Substring(4);
}
var args = new object[0];
if (msg.Properties["__Args"] != null)
{
args = (object[]) msg.Properties["__Args"];
}
var res = typeof (T).InvokeMember(meth,
bf
, null, obj, args);
if ((bf && BindingFlags.SetProperty) == BindingFlags.SetProperty)
{
OnPropertyChanged(meth);
}
return new ReturnMessage(res, null, 0, null, null);
}
public event PropertyChangedEventHandler PropertyChanged;
private void OnPropertyChanged(string propertyName)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
}
<强>用法强>
User yourplainUser = GetFromBackEnd();
// if I've the generics wrong, sorry...
var bindUser = Bindable<User>.BuildProxy(yourplainUser);
// var bindUser = new Bindable<User>(yourplainUser).Proxy;
您现在可以在WPF表单中使用bindUser
对象,至少它支持INotifyPropertyChanged,并且对您的应用程序(和/或消费者)更加透明。