Ale*_*dro 3 c# proxy-classes mvvm inotifypropertychanged
我想摆脱模型类中占用空间和重复性的RaisePropertyChanged-Properties.我想要我的模特课......
public class ProductWorkItem : NotificationObject
{
private string name;
public string Name
{
get { return name; }
set {
if (value == name) return;
name = value; RaisePropertyChanged(() => Name);
}
}
private string description;
public string Description
{
get { return description; }
set {
if (value == description) return;
description = value; RaisePropertyChanged(() => Description);
}
}
private string brand;
public string Brand
{
get { return brand; }
set {
if (value == brand) return;
brand = value; RaisePropertyChanged(() => Brand);
}
}
}
Run Code Online (Sandbox Code Playgroud)
...看起来像这样简单:(但是当属性改变时通知视图)
public class ProductWorkItem
{
public string Name{ get; set; }
public string Description{ get; set; }
public string Brand{ get; set; }
}
Run Code Online (Sandbox Code Playgroud)
这可以通过某种代理类来实现吗?
我想避免为每个模型类编写代理.
我知道在"vanilla"C#中没有简单且可维护的方法,但你可以用方面实现这一点.我已经使用了PostSharp,它的缺点是作为付费的第三方产品,但有一个免费版本,你也可以这样做.PostSharp利用目标指定,继承等属性的优势,并将它们扩展到方面.
然后LocationInterceptionAspect,您可以定义一个覆盖OnSetValue方法来调用您的RaisePropertyChanged委托.然后,您可以使用使用aspect属性修饰的自动生成的属性.
PostSharp的付费版本允许您在类级别执行此操作,因此您只需要一个属性(或者不需要,如果您修饰基类并将属性定义为可继承).这在PostSharp网站上描述为一个用例InstanceLevelAspect
我在命名空间中找到了这个类...它可以让您拦截绑定目标上对绑定源上的System.Dynamic实际DataBinding调用。DependencyObjectProperty
因此,现在可以做的是实现一个类(我们称之为DynamicNpcProxy)INotifyPropertyChanged,该类实现 、 派生自DynamicObject并重写TryGetMember和TrySetMember方法。
public class DynamicNpcProxy : DynamicObject, INotifyPropertyChanged
{
public DynamicNpcProxy(object proxiedObject)
{
ProxiedObject = proxiedObject;
}
//...
public object ProxiedObject { get; set; }
public override bool TrySetMember(SetMemberBinder binder, object value)
{
SetMember(binder.Name, value);
return true;
}
protected virtual void SetMember(string propertyName, object value)
{
GetPropertyInfo(propertyName).SetValue(ProxiedObject, value, null);
if (PropertyChanged != null)
PropertyChanged(ProxiedObject, new PropertyChangedEventArgs(propertyName));
}
protected PropertyInfo GetPropertyInfo(string propertyName)
{
return ProxiedObject.GetType().GetProperty(propertyName);
}
// override bool TryGetMember(...)
}
Run Code Online (Sandbox Code Playgroud)
要使其正常工作,请将代理包装在当前的绑定源周围,替换它们,然后让我们DynamicObject完成剩下的工作。
在 ViewModel.cs 中:
IList<ProductWorkItem> items;
//... assign items
var proxies = items.Select(p => new DynamicNpcProxy(p)).ToList();
ICollectionView Products = CollectionViewSource.GetDefaultView(proxies);
Run Code Online (Sandbox Code Playgroud)
在 View.xaml 中:
<TextBox Text="{Binding Products.CurrentItem.Name}" />
<TextBox Text="{Binding Products.CurrentItem.Description}" />
Run Code Online (Sandbox Code Playgroud)
你最终得到的是这样的:

另请查看这篇文章,其中code project提供了更多信息......