我正在尝试使用Castle Windsor Dynamic Proxies实现WPF ViewModel。我的想法是,我想提供一个接口(下面的IPerson就足够了),一个具体的支持类和一个拦截器(用于提供INotifyPropertyChanged的自动实现)。拦截器实现在这里:http://www.hightech.ir/SeeSharp/Best-Implementation-Of-INotifyPropertyChange-Ever
我看到的问题是,当我将模型绑定到WPF控件时,控件不会将模型视为实现INotifyPropertyChanged。我相信(但不确定)这是因为Windsor明确地实现了接口,而WPF似乎期望它们是隐含的。
有没有办法让这项工作成功,以便拦截器捕获对模型的更改并将其提升到模型?
所有版本的库都是最新版本:Castle.Core 2.5.1.0和Windsor 2.5.1.0
代码如下:
// 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);
}
}
答案 0 :(得分:4)
所以答案结果相当简单......来自http://www.hightech.ir/SeeSharp/Best-Implementation-Of-INotifyPropertyChange-Ever的代码将拦截器定义为:
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));
}
}
在我的例子中,InvocationTarget根本不是作为PropertyChanged的第一个参数传递的正确实体(因为我正在生成代理)。将最后一个功能更改为以下解决了问题:
private void FireNotificationChanged(IInvocation invocation)
{
var propertyName = invocation.Method.Name.Substring(4);
_subscribers(invocation.Proxy, new PropertyChangedEventArgs(propertyName));
}
答案 1 :(得分:0)
我认为你需要让你的Class的成员实现虚拟接口。