Report guards as best we can if the target does not implement INPC

Fixes #214
This commit is contained in:
Antony Male 2021-02-15 08:53:39 +00:00
parent 3101fcd99a
commit c82cdb9321
2 changed files with 35 additions and 18 deletions

View File

@ -65,32 +65,31 @@ namespace Stylet.Xaml
/// <param name="newTarget">New target</param>
protected internal override void OnTargetChanged(object oldTarget, object newTarget)
{
var oldInpc = oldTarget as INotifyPropertyChanged;
if (oldInpc != null)
if (oldTarget is INotifyPropertyChanged oldInpc)
PropertyChangedEventManager.RemoveHandler(oldInpc, this.PropertyChangedHandler, this.GuardName);
this.guardPropertyGetter = null;
var inpc = newTarget as INotifyPropertyChanged;
if (inpc != null)
var guardPropertyInfo = newTarget?.GetType().GetProperty(this.GuardName);
if (guardPropertyInfo != null)
{
var guardPropertyInfo = newTarget.GetType().GetProperty(this.GuardName);
if (guardPropertyInfo != null)
if (guardPropertyInfo.PropertyType == typeof(bool))
{
if (guardPropertyInfo.PropertyType == typeof(bool))
{
var targetExpression = Expressions.Expression.Constant(newTarget);
var propertyAccess = Expressions.Expression.Property(targetExpression, guardPropertyInfo);
this.guardPropertyGetter = Expressions.Expression.Lambda<Func<bool>>(propertyAccess).Compile();
}
else
{
logger.Warn("Found guard property {0} for action {1} on target {2}, but its return type wasn't bool. Therefore, ignoring", this.GuardName, this.MethodName, newTarget);
}
var targetExpression = Expressions.Expression.Constant(newTarget);
var propertyAccess = Expressions.Expression.Property(targetExpression, guardPropertyInfo);
this.guardPropertyGetter = Expressions.Expression.Lambda<Func<bool>>(propertyAccess).Compile();
}
else
{
logger.Warn("Found guard property {0} for action {1} on target {2}, but its return type wasn't bool. Therefore, ignoring", this.GuardName, this.MethodName, newTarget);
}
}
if (this.guardPropertyGetter != null)
if (this.guardPropertyGetter != null)
{
if (newTarget is INotifyPropertyChanged inpc)
PropertyChangedEventManager.AddHandler(inpc, this.PropertyChangedHandler, this.GuardName);
else
logger.Warn("Found guard property {0} for action {1} on target {2}, but the target doesn't implement INotifyPropertyChanged, so changes won't be observed", this.GuardName, this.MethodName, newTarget);
}
this.UpdateCanExecute();

View File

@ -62,6 +62,12 @@ namespace StyletUnitTests
{
}
private class TargetWithoutInpc
{
public bool CanDoSomething => false;
public void DoSomething() { }
}
private DependencyObject subject;
private Target target;
@ -171,6 +177,18 @@ namespace StyletUnitTests
Assert.True(eventRaised);
}
[Test]
public void FetchesGuardPropertyWhenTargetDoesNotImplementInpc()
{
var target = new TargetWithoutInpc();
var cmd = new CommandAction(this.subject, null, "DoSomething", ActionUnavailableBehaviour.Throw, ActionUnavailableBehaviour.Throw);
bool eventRaised = false;
cmd.CanExecuteChanged += (o, e) => eventRaised = true;
View.SetActionTarget(this.subject, target);
Assert.True(eventRaised);
Assert.False(cmd.CanExecute(null));
}
[Test]
public void RaisesEventWhenTargetChanges()
{