0

正如您在WPF应用程序中所知道的,如果要将特定类的某些属性绑定到控件的属性,则必须实现INotifyPropertyChanged该类的接口。

现在考虑我们有许多没有实现的普通类INotifyPropertyChanged。它们是非常简单的类,例如这个例子:

    public class User : ModelBase
{
    public int Id { get; set; }
    public string UserName { get; set; }
    public string Password { get; set; }
//  ...
}

例如,我想将 绑定UserName到 a 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.

当然,我不确定这是不是好方法!这只是澄清我的问题的一个想法。

请不要告诉我没有办法或不可能!有数百种型号!!!

谢谢。

4

3 回答 3

1

如果您无法修改源类,您可以研究 Unity 新版本中的“行为注入”功能。“行为注入”功能允许您将一个类连接到 BEHAVE,就好像它从 INotifyPropertyChanged 继承一样,而无需修改类本身。

昨天这里有一个非常相似的主题,它提供了帮助您入门的链接。Unity 团队甚至为您提供了注入器的源代码,以便在 POCO 类上创建 INotifyPropertyChanged。我已经使用过它并且可以证明它有效。这会影响性能,但如果您不想修改源类但仍享受 WPF 绑定的功能,那么这就是游戏的一部分。

于 2013-06-30T17:26:52.480 回答
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;

您现在可以bindUser在 WPF 表单中使用该对象,至少它支持 INotifyPropertyChanged 并且对您的应用程序(和/或消费者)更加透明。

于 2013-06-30T13:43:14.890 回答
0

将您的 InNotifyPropertyChanged 实现移动到基类,并让您的视图模型继承该基类。

基类

public class BaseNotify
{
    public event PropertyChangedEventHandler PropertyChanged;
    protected void OnPropertyChanged(string propertyName)
    {
       if (PropertyChanged != null)
       {
           PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
       }
    }
}

你的视图模型类

public class User : BaseNotify
{

    private string userName;
    public string UserName 
    { 

        get { return userName; }
        set
        {
            userName = value;
            OnPropertyChanged("UserName");
        }
    }
}
于 2013-06-30T11:55:08.460 回答