private object HandleDependencyObject(IProvideValueTarget valueService, DependencyObject targetObject, DependencyObject rootObject) { switch (valueService.TargetProperty) { case DependencyProperty dependencyProperty when dependencyProperty.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)); case EventInfo eventInfo: { var ec = new EventAction(targetObject, rootObject, eventInfo.EventHandlerType, this.Method, this.EventNullTargetBehaviour, this.EventActionNotFoundBehaviour); return(ec.GetDelegate()); } case MethodInfo methodInfo: // For attached events { var parameters = methodInfo.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("Action used with an attached event (or something similar) which didn't follow the normal pattern"); } default: throw new ArgumentException("Can only use ActionExtension with a Command property or an event handler"); } }
private object HandleCommandBinding(DependencyObject rootObject, Type propertyType) { if (rootObject == null) { throw new InvalidOperationException("Action may only be used with CommandBinding from a XAML view (unable to retrieve IRootObjectProvider.RootObject)"); } var ec = new EventAction(rootObject, null, propertyType, this.Method, this.EventNullTargetBehaviour, this.EventActionNotFoundBehaviour); return(ec.GetDelegate()); }
/// <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"); }
/// <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 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 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 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 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 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 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); }