Пример #1
0
        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");
            }
        }
Пример #2
0
        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());
        }
Пример #3
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");
        }
Пример #4
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");
        }
Пример #5
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);
        }
Пример #6
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);
 }
Пример #7
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);
 }
Пример #8
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());
 }
Пример #9
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);
        }
Пример #10
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);
 }
Пример #11
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);
 }
Пример #12
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);
 }
Пример #13
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);
 }