我有一个MVVM模型,我的视图模型包含observableCollection<RfidData>
。
每当更新此数据时,我想在属性上调用RaisePropertyChanged()
。
我在某处看到它可以用Unity IoC容器非常巧妙地完成,但我再也找不到了。
这是我的班级:
public class RfidData : INotifyPropertyChanged
{
private bool _checkedIn = false;
private Guid _id;
private int _collectorId;
private DateTime _checkInTime;
private string _name = "Test Name";
public bool CheckedIn
{
get { return _checkedIn; }
set { _checkedIn = value; RaisePropertyChanged(); }
}
public Guid Id
{
get {return _id;}
set { _id = value; RaisePropertyChanged(); }
}
public int CollectorId
{
set { _collectorId = value; RaisePropertyChanged(); }
get { return _collectorId; }
}
public DateTime CheckInTime
{
set { _checkInTime = value; RaisePropertyChanged(); }
get { return _checkInTime; }
}
public string Name
{
set { _name = value; RaisePropertyChanged(); }
get { return _name; }
}
protected virtual void RaisePropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
public event PropertyChangedEventHandler PropertyChanged;
}
有什么建议吗?
答案 0 :(得分:1)
我认为你正在寻找拦截器。这是一个如何使用它的例子 Unity Interceptor
答案 1 :(得分:0)
对我有用的解决方案:
使用
export DPDK_BUILD=$DPDK_DIR/x86_64-native-linuxapp-gcc/
./configure --with-dpdk=$DPDK_BUILD
make
make install
属性定义类:
virtual
public class RfidData : BaseViewModel
{
public RfidData(Guid id)
{
Id = id;
}
public virtual int CollectorId { get; set; }
public virtual DateTime CheckInTime { get; set; }
public virtual string Name { get; set; }
public virtual bool CheckedIn { get; set; }
public virtual DateTime TimeStamp { get; set; }
public virtual Guid Id { get; }
}
将执行RaidPropertyChange()方法:
BaseViewModel
从@bilpor's link.创建几乎 rip-off
调用的方法因调用public class BaseViewModel : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
[NotifyPropertyChangedInvocator]
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
而不是旧RaisePropertyChanged
而不同。
我相信使用像PropertyChanged
这样的新方法会有所改善,但我还没有调查过它。
[CallerMemberName]
最后,使用Unity Intercepter类注册类using System;
using System.ComponentModel;
using System.Reflection;
using Microsoft.Practices.Unity.InterceptionExtension;
public class PropertyChangedCallHandler : ICallHandler
{
public int Order { get; set; }
public IMethodReturn Invoke(IMethodInvocation input, GetNextHandlerDelegate getNext)
{
//Only if not same value as current, and it's a 'set' called
var shouldRaise = ShouldRaiseEvent(input);
var res = getNext()(input, getNext);
if (res.Exception == null && shouldRaise)
RaiseEvent(input);
return res;
}
private bool ShouldRaiseEvent(IMethodInvocation input)
{
var methodBase = input.MethodBase;
//Is the method a property setter?
if (!methodBase.IsSpecialName || !methodBase.Name.StartsWith("set_"))
{
return false;
}
//Get the name of the property out so we can use it to raise a
//property changed event
string propertyName = methodBase.Name.Substring(4);
//Retrieve the property getter
PropertyInfo property = methodBase.ReflectedType.GetProperty(propertyName);
MethodInfo getMethod = property.GetGetMethod();
//IF the property has no get method, we don't care
if (getMethod == null)
{
return false;
}
//Get the current value out
object oldValue = getMethod.Invoke(input.Target, null);
//Get the updated value
object value = input.Arguments[0];
//Is the new value null?
if (value != null)
{
//Is the new value different from the old value?
if (value.Equals(oldValue) == false)
{
return true;
}
}
else
{
//Is the new value (null) different from the
//old value (non-null)?
if (value != oldValue)
{
return true;
}
}
return false;
}
private void RaiseEvent(IMethodInvocation input)
{
FieldInfo field = null;
//Get a reference to the PropertyChanged event out of the current
//type or one of the base types
var type = input.MethodBase.ReflectedType;
while (field == null && type != null)
{
//This differs from the original
field = type.GetField("RaisePropertyChanged", BindingFlags.Instance | BindingFlags.NonPublic);
type = type.BaseType;
}
//If we found the PropertyChanged event
if (field != null)
{
//Get the event handler if there is one
var evt = field.GetValue(input.Target) as MulticastDelegate;
if (evt != null)
{
//Get the property name out
string propertyName = input.MethodBase.Name.Substring(4);
//Invoke the property changed event handlers
evt.DynamicInvoke(input.Target, new PropertyChangedEventArgs(propertyName));
}
}
}
}
:
RfidData
但是,奇怪的是:
实例化时,通常是var notificationPolicy = _container.AddNewExtension<Interception>()
.RegisterType<BaseViewModel, RfidData>()
.Configure<Interception>()
.SetDefaultInterceptorFor(userControlType, new VirtualMethodInterceptor())
.AddPolicy("NotificationPolicy");
notificationPolicy.AddMatchingRule(new PropertyMatchingRule("*", PropertyMatchingOption.Set));
notificationPolicy.AddCallHandler<PropertyChangedCallHandler>();
,但我通过contain.Resolve<RfidData>()
方法获取所有数据。
但它接受正确的类型。