本文介绍了温莎城堡代理,隐接口和WPF绑定的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图使用温莎城堡动态代理实现一个WPF视图模型。这个想法是,我想提供一个接口(下图IPerson应足以作为一个例子),具体支持类,和一个拦截器(提供自动执行INotifyPropertyChanged的的)。拦截器的实现是在这里:的

这是我看到的问题是,当我结合我的模型WPF控件,这些控件没有看到模型作为实施INotifyPropertyChanged的。我相信,(但我不知道),这是因为温莎是实现接口明确,并WPF似乎期望他们是隐含的。

有什么办法,使这项工作,这样对模型的变化是由拦截器捕获并提出到模型?

库的所有版本都是最新的:Castle.Core 2.5.1.0和2.5.1.0温莎

code是如下:

  //我的模型界面
公共接口IPerson:INotifyPropertyChanged的
{
    串首先{搞定;组; }
    字符串名字{获得;组; }
    DateTime的生日{搞定;组; }
}//我的具体类:
[拦截器(typeof运算(NotifyPropertyChangedInterceptor))]
类人:IPerson
{
    公共事件PropertyChangedEventHandler的PropertyChanged =(S,E)=> {};
    公共字符串首先{搞定;组; }
    公共字符串名字{获得;组; }
    公众的DateTime生日{搞定;组; }
}//我的温莎安装
公共类安装程序:IWindsorInstaller
{
    公共无效安装(IWindsorContainer容器,IConfigurationStore店)
    {
        container.Register(
            Component.For< NotifyPropertyChangedInterceptor>()
            .ImplementedBy< NotifyPropertyChangedInterceptor>()
            .LifeStyle.Transient);
        container.Register(
            Component.For< IPerson,INotifyPropertyChanged的>()
            .ImplementedBy<&人GT;()LifeStyle.Transient)。
    }
}


解决方案

因此​​,答案竟然是相当简单的...从的定义拦截为:

 公共类NotifyPropertyChangedInterceptor:IInterceptor
{
    私人PropertyChangedEventHandler _subscribers =委托{};    公共无效拦截(IInvocation调用)
    {
        如果(invocation.Method.DeclaringType == typeof运算(INotifyPropertyChanged的))
        {
            HandleSubscription(调用);
            返回;
        }        invocation.Proceed();        如果(invocation.Method.Name.StartsWith(SET_))
        {
            FireNotificationChanged(调用);
        }
    }    私人无效HandleSubscription(IInvocation调用)
    {
        无功处理=(PropertyChangedEventHandler)invocation.Arguments [0];        如果(invocation.Method.Name.StartsWith(add_))
        {
            _subscribers + =处理程序;
        }
        其他
        {
            _subscribers - =处理程序;
        }
    }    私人无效FireNotificationChanged(IInvocation调用)
    {
        变种propertyName的= invocation.Method.Name.Substring(4);
        _subscribers(invocation.InvocationTarget,新PropertyChangedEventArgs(propertyName的));
    }
}

在我的情况下,InvocationTarget只是没有合适的实体路过的第一个参数的PropertyChanged(因为我生成代理)。改变最后一个函数以下解决了这一问题:

 私人无效FireNotificationChanged(IInvocation调用)
{
    变种propertyName的= invocation.Method.Name.Substring(4);
    _subscribers(invocation.Proxy,新PropertyChangedEventArgs(propertyName的));
}

I am attempting to implement a WPF ViewModel using Castle Windsor Dynamic Proxies. The idea is that I want to supply an interface (IPerson below should suffice as an example), a concrete backing class, and an interceptor (for providing automatic implementation of INotifyPropertyChanged). The interceptor implementation is here: http://www.hightech.ir/SeeSharp/Best-Implementation-Of-INotifyPropertyChange-Ever

The problem that I am seeing is that when I bind my models to WPF controls, the controls don't see the models as implementing INotifyPropertyChanged. I believe (but am not sure) that this is because Windsor is implementing the interfaces explicitly, and WPF seems to expect them to be implicit.

Is there any way to make this work, so that changes to the model are caught by the interceptor and raised to the model?

All versions of the libraries are the latest: Castle.Core 2.5.1.0 and Windsor 2.5.1.0

Code is as follows:

// My model's interface
public interface IPerson : INotifyPropertyChanged
{
    string First { get; set; }
    string LastName { get; set; }
    DateTime Birthdate { get; set; }
}

// My concrete class:
[Interceptor(typeof(NotifyPropertyChangedInterceptor))]
class Person : IPerson
{
    public event PropertyChangedEventHandler PropertyChanged = (s,e)=> { };
    public string First { get; set; }
    public string LastName { get; set; }
    public DateTime Birthdate { get; set; }
}

// My windsor installer
public class Installer : IWindsorInstaller
{
    public void Install(IWindsorContainer container, IConfigurationStore store)
    {
        container.Register(
            Component.For<NotifyPropertyChangedInterceptor>()
            .ImplementedBy<NotifyPropertyChangedInterceptor>()
            .LifeStyle.Transient);
        container.Register(
            Component.For<IPerson, INotifyPropertyChanged>()
            .ImplementedBy<Person>().LifeStyle.Transient);
    }
}
解决方案

So the answer turned out to be fairly straightforward... The code from http://www.hightech.ir/SeeSharp/Best-Implementation-Of-INotifyPropertyChange-Ever defines the interceptor as:

public class NotifyPropertyChangedInterceptor : IInterceptor
{
    private PropertyChangedEventHandler _subscribers = delegate { };

    public void Intercept(IInvocation invocation)
    {
        if (invocation.Method.DeclaringType == typeof(INotifyPropertyChanged))
        {
            HandleSubscription(invocation);
            return;
        }

        invocation.Proceed();

        if (invocation.Method.Name.StartsWith("set_"))
        {
            FireNotificationChanged(invocation);
        }
    }

    private void HandleSubscription(IInvocation invocation)
    {
        var handler = (PropertyChangedEventHandler)invocation.Arguments[0];

        if (invocation.Method.Name.StartsWith("add_"))
        {
            _subscribers += handler;
        }
        else
        {
            _subscribers -= handler;
        }
    }

    private void FireNotificationChanged(IInvocation invocation)
    {
        var propertyName = invocation.Method.Name.Substring(4);
        _subscribers(invocation.InvocationTarget, new PropertyChangedEventArgs(propertyName));
    }
}

In my case, the InvocationTarget was simply not the right entity to be passing as the first argument to PropertyChanged (because I am generating a proxy). Changing the last function to the following fixed the problem:

private void FireNotificationChanged(IInvocation invocation)
{
    var propertyName = invocation.Method.Name.Substring(4);
    _subscribers(invocation.Proxy, new PropertyChangedEventArgs(propertyName));
}

这篇关于温莎城堡代理,隐接口和WPF绑定的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

09-05 21:36