/// <summary> /// When implemented in a derived class, returns an object that is provided as the value of the target property for this markup extension. /// </summary> /// <param name="serviceProvider">A service provider helper that can provide services for the markup extension.</param> /// <returns>The object value to set on the property where the extension is applied.</returns> public override object ProvideValue(IServiceProvider serviceProvider) { if (this.Method == null) throw new InvalidOperationException("Method has not been set"); var valueService = (IProvideValueTarget)serviceProvider.GetService(typeof(IProvideValueTarget)); // Seems this is the case when we're in a template. We'll get called again properly in a second. // http://social.msdn.microsoft.com/Forums/vstudio/en-US/a9ead3d5-a4e4-4f9c-b507-b7a7d530c6a9/gaining-access-to-target-object-instead-of-shareddp-in-custom-markupextensions-providevalue-method?forum=wpf if (!(valueService.TargetObject is DependencyObject)) return this; var targetObject = (DependencyObject)valueService.TargetObject; var rootObjectProvider = (IRootObjectProvider)serviceProvider.GetService(typeof(IRootObjectProvider)); var rootObject = rootObjectProvider == null ? null : rootObjectProvider.RootObject as DependencyObject; var propertyAsDependencyProperty = valueService.TargetProperty as DependencyProperty; if (propertyAsDependencyProperty != null && propertyAsDependencyProperty.PropertyType == typeof(ICommand)) { // If they're in design mode and haven't set View.ActionTarget, default to looking sensible return new CommandAction(targetObject, rootObject, this.Method, this.CommandNullTargetBehaviour, this.CommandActionNotFoundBehaviour); } var propertyAsEventInfo = valueService.TargetProperty as EventInfo; if (propertyAsEventInfo != null) { var ec = new EventAction(targetObject, rootObject, propertyAsEventInfo.EventHandlerType, this.Method, this.EventNullTargetBehaviour, this.EventActionNotFoundBehaviour); return ec.GetDelegate(); } // For attached events var propertyAsMethodInfo = valueService.TargetProperty as MethodInfo; if (propertyAsMethodInfo != null) { var parameters = propertyAsMethodInfo.GetParameters(); if (parameters.Length == 2 && typeof(Delegate).IsAssignableFrom(parameters[1].ParameterType)) { var ec = new EventAction(targetObject, rootObject, parameters[1].ParameterType, this.Method, this.EventNullTargetBehaviour, this.EventActionNotFoundBehaviour); return ec.GetDelegate(); } } throw new ArgumentException("Can only use ActionExtension with a Command property or an event handler"); }
public void DoesNotRetainTarget() { var view = new DependencyObject(); var weakView = new WeakReference(view); View.SetActionTarget(view, this.target); var cmd = new EventAction(view, null, this.eventInfo.EventHandlerType, "DoSomething", ActionUnavailableBehaviour.Throw, ActionUnavailableBehaviour.Throw); cmd = null; view = null; GC.Collect(); Assert.IsFalse(weakView.IsAlive); }
public void OperatesAfterCollection() { var view = new DependencyObject(); var cmd = new EventAction(view, null, this.eventInfo.EventHandlerType, "DoSomething", ActionUnavailableBehaviour.Throw, ActionUnavailableBehaviour.Throw); GC.Collect(); View.SetActionTarget(view, this.target); cmd.GetDelegate().DynamicInvoke(null, null); Assert.IsTrue(this.target.DoSomethingCalled); }
public void PropagatesActionException() { var cmd = new EventAction(this.subject, null, this.eventInfo.EventHandlerType, "DoSomethingUnsuccessfully", ActionUnavailableBehaviour.Enable, ActionUnavailableBehaviour.Enable); var e = Assert.Throws<TargetInvocationException>(() => cmd.GetDelegate().DynamicInvoke(null, null)); Assert.IsInstanceOf<InvalidOperationException>(e.InnerException); Assert.AreEqual("foo", e.InnerException.Message); }
public void ExecuteThrowsIfActionTargetIsDefault() { View.SetActionTarget(this.subject, View.InitialActionTarget); var cmd = new EventAction(this.subject, null, this.eventInfo.EventHandlerType, "DoSomething", ActionUnavailableBehaviour.Throw, ActionUnavailableBehaviour.Throw); var e = Assert.Throws<TargetInvocationException>(() => cmd.GetDelegate().DynamicInvoke(null, null)); Assert.IsInstanceOf<ActionNotSetException>(e.InnerException); }
public void InvokingCommandCallsMethodWithSenderAndDependencyChangedEventArgs() { var cmd = new EventAction(this.subject, null, this.dependencyChangedEventInfo.EventHandlerType, "DoSomethingWithObjectAndDependencyChangedEventArgs", ActionUnavailableBehaviour.Enable, ActionUnavailableBehaviour.Enable); var sender = new object(); var arg = new DependencyPropertyChangedEventArgs(); cmd.GetDelegate().DynamicInvoke(sender, arg); Assert.AreEqual(sender, this.target.Sender); Assert.AreEqual(arg, this.target.DependencyChangedEventArgs); }
public void BadEventHandlerSignatureThrows() { var cmd = new EventAction(this.subject, null, typeof(Subject).GetEvent("BadEventHandler").EventHandlerType, "DoSomething", ActionUnavailableBehaviour.Enable, ActionUnavailableBehaviour.Enable); Assert.Throws<ActionEventSignatureInvalidException>(() => cmd.GetDelegate()); }
public void InvokingCommandCallsMethodWithEventArgs() { var cmd = new EventAction(this.subject, null, this.eventInfo.EventHandlerType, "DoSomethingWithEventArgs", ActionUnavailableBehaviour.Enable, ActionUnavailableBehaviour.Enable); var arg = new RoutedEventArgs(); cmd.GetDelegate().DynamicInvoke(null, arg); Assert.AreEqual(arg, this.target.EventArgs); }
public void InvokingCommandCallsMethod() { var cmd = new EventAction(this.subject, null, this.eventInfo.EventHandlerType, "DoSomething", ActionUnavailableBehaviour.Enable, ActionUnavailableBehaviour.Enable); cmd.GetDelegate().DynamicInvoke(null, null); Assert.True(this.target.DoSomethingCalled); }
public void InvokingCommandDoesNothingIfActionIsNonExistent() { var cmd = new EventAction(this.subject, null, this.eventInfo.EventHandlerType, "DoSomething", ActionUnavailableBehaviour.Enable, ActionUnavailableBehaviour.Enable); View.SetActionTarget(this.subject, new Target2()); cmd.GetDelegate().DynamicInvoke(null, null); }
public void ThrowsWhenClickedIfActionNonExistentBehaviourIsThrowAndActionIsNonExistent() { var cmd = new EventAction(this.subject, null, this.eventInfo.EventHandlerType, "DoSomething", ActionUnavailableBehaviour.Enable, ActionUnavailableBehaviour.Throw); Assert.DoesNotThrow(() => View.SetActionTarget(this.subject, new Target2())); var e = Assert.Throws<TargetInvocationException>(() => cmd.GetDelegate().DynamicInvoke(null, new RoutedEventArgs())); Assert.IsInstanceOf<ActionNotFoundException>(e.InnerException); }
public void ThrowsIfTargetNullBehaviourIsThrowAndTargetBecomesNull() { var cmd = new EventAction(this.subject, null, this.eventInfo.EventHandlerType, "DoSomething", ActionUnavailableBehaviour.Throw, ActionUnavailableBehaviour.Enable); Assert.Throws<ActionTargetNullException>(() => View.SetActionTarget(this.subject, null)); }