예제 #1
0
        /// <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");
        }
예제 #2
0
        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);
        }
예제 #3
0
        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);
        }
예제 #4
0
 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);
 }
예제 #5
0
 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);
 }
예제 #6
0
        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);
        }
예제 #7
0
 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());
 }
예제 #8
0
 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);
 }
예제 #9
0
 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);
 }
예제 #10
0
 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);
 }
예제 #11
0
 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);
 }
예제 #12
0
 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));
 }