I've been doing a refactor of an existing application, and I am attempting to use an Attribute on a property to trigger the NotifyPropertyChanged event using Unity interception. I got to the point where the event was firing, but the controls were not updating.
I wasn't sure if it was invoking the event correctly, so on my ViewModelBase I created a DispatchPropertyChanged method that invokes the property changed event. This method works to launch property changed when called directly from a view model, but when called from a ViewModel retrieved through reflection inside the intercept handler, it doesn't work.
I've inserted a link to the https://www.dropbox.com/s/9qg2n0gd2n62elc/WPFUnityTest.zip. If you open this solution and run the application, then click the "Reset" button, you'll see that the "Normal" text box updates, but the "Unity" text box does not update.
If you place a breakpoint at line 65 of the MainWindowViewModel and line 53 of the NotifyPropertyChangedHandler you'll see that the handler is working, the dispatch method is being called, and the event is being invoked. However, only the "Normal" one updates.
Any help on why the "Unity" text box isn't updating would be wonderful, thanks!
Amanda
EDIT:
Sorry for not including this originally, I really had no idea where the problem was. This was the original code for the interception behavior that was correct below:
public class NotifyPropertyChangedHandler : IInterceptionBehavior
{
public IMethodReturn Invoke(IMethodInvocation input, GetNextInterceptionBehaviorDelegate getNext)
{
var npcAttribute = getNotifyPropertyChangedAttributeForSetter(input) as NotifyPropertyChangedAttribute;
if (npcAttribute != null)
{
if (npcAttribute.TimingOption == PropertyChangedTiming.Always||
shouldRaiseEvent(input))
{
raiseEvent(input);
}
}
return getNext()(input, getNext);
}
public IEnumerable<Type> GetRequiredInterfaces()
{
return new[] { typeof(INotifyPropertyChanged) };
}
public bool WillExecute { get { return true; } }
private object getNotifyPropertyChangedAttributeForSetter(IMethodInvocation input)
{
if (!input.MethodBase.Name.StartsWith("set_"))
{
return null;
}
return input.MethodBase.ReflectedType.GetProperty(input.MethodBase.Name.Substring(4))
.GetCustomAttributes(true).SingleOrDefault(attr => attr.GetType() == typeof (NotifyPropertyChangedAttribute));
}
private void raiseEvent(IMethodInvocation input)
{
raiseEvent(input, new PropertyChangedEventArgs(input.MethodBase.Name.Substring(4)));
}
private void raiseEvent(IMethodInvocation input, PropertyChangedEventArgs eventArgs)
{
var viewModel = input.Target as ViewModelBase;
if (viewModel != null)
{
viewModel.DispatchPropertyChangedEvent(eventArgs.PropertyName);
}
}
private static bool shouldRaiseEvent(IMethodInvocation input)
{
var methodBase = input.MethodBase;
if (!methodBase.IsSpecialName || !methodBase.Name.StartsWith("set_"))
{
return false;
}
var propertyName = methodBase.Name.Substring(4);
var property = methodBase.ReflectedType.GetProperty(propertyName);
var getMethod = property.GetGetMethod();
if (getMethod == null)
{
return false;
}
var oldValue = getMethod.Invoke(input.Target, null);
var value = input.Arguments[0];
return (value == null) ? oldValue !=null :
!value.Equals(oldValue);
}
}