/// <summary> /// Creates the delegate with requested type from a method. /// </summary> /// <param name="methodName">The method name that can be used as a delegate.</param> /// <param name="sourceObject">The source object that contains a method.</param> /// <param name="desiredDelegateType">The delegate type.</param> /// <returns></returns> public static Object EventHandlerDelegateFromMethod(string methodName, object sourceObject, Type desiredDelegateType) { MethodInfo methodInfo = sourceObject.GetMethodInfo(methodName); if (methodInfo == null) { List <Tuple <Type, object> > locatedViewModels = BindHelper.LocateAppendedViewModels(sourceObject); foreach (var model in locatedViewModels) { methodInfo = model.Item2.GetMethodInfo(methodName); if (methodInfo != null) { sourceObject = model.Item2; break; } } } if (methodInfo == null) { throw new ArgumentException("DelegateFromMethod - cannot resolve method " + methodName); } return(EventHandlerDelegateFromMethodInfo(sourceObject, desiredDelegateType, methodInfo)); }
internal object ResolvePropertyValues(object sourceBaseProvided) { if (sourceBaseProvided == null) { return(null); } EventInfo outerEvent = null; PropertyInfo outerProperty = null; Action <object> executeDelegate = null; Func <object, bool> canExecuteDelegate = null; Type type = sourceBaseProvided.GetType(); if ((!String.IsNullOrEmpty(ExecuteMethodName)) && (!String.IsNullOrEmpty(ExecutePropertyName))) { throw new ArgumentException("BindCommandBase - Should be set only one property 'ExecuteMethodName' or 'ExecutePropertyName'"); } if ((!String.IsNullOrEmpty(CanExecuteBooleanPropertyName)) && (!String.IsNullOrEmpty(CanExecuteMethodName) || !String.IsNullOrEmpty(CanExecutePropertyName) || !String.IsNullOrEmpty(EventToInvokeCanExecuteChanged) || !String.IsNullOrEmpty(PropertyActionCanExecuteChanged))) { throw new ArgumentException("BindCommandBase - Should be set only one property 'CanExecuteBooleanPropertyName'"); } if ((!String.IsNullOrEmpty(CanExecuteMethodName)) && (!String.IsNullOrEmpty(CanExecutePropertyName))) { throw new ArgumentException("BindCommandBase - Should be set only one property 'CanExecuteMethodName' or 'CanExecutePropertyName'"); } if ((!String.IsNullOrEmpty(EventToInvokeCanExecuteChanged)) && (!String.IsNullOrEmpty(PropertyActionCanExecuteChanged))) { throw new ArgumentException("BindCommandBase - Should be set only one property 'EventToInvokeCanExecuteChanged' or 'PropertyActionCanExecuteChanged'"); } if (!String.IsNullOrEmpty(ExecuteMethodName)) { MethodInfo executeMethod = type.GetMethodInfo(ExecuteMethodName); if (executeMethod == null) { List <Tuple <Type, object> > locatedViewModels = BindHelper.LocateAppendedViewModels(sourceBaseProvided); foreach (var model in locatedViewModels) { executeMethod = model.Item2.GetMethodInfo(ExecuteMethodName); if (executeMethod != null) { sourceBaseProvided = model.Item2; type = model.Item1; break; } } } if (executeMethod == null) { throw new ArgumentException("BindCommandBase - cannot resolve 'ExecuteMethodName' method " + ExecuteMethodName); } if (executeMethod.IsStatic) { #if WINDOWS_UWP executeDelegate = (Action <object>)executeMethod.CreateDelegate(typeof(Action <object>)); #else executeDelegate = (Action <object>)Delegate.CreateDelegate(typeof(Action <object>), executeMethod); #endif } else { #if WINDOWS_UWP executeDelegate = (Action <object>)executeMethod.CreateDelegate(typeof(Action <object>), sourceBaseProvided); #else executeDelegate = (Action <object>)Delegate.CreateDelegate(typeof(Action <object>), sourceBaseProvided, executeMethod); #endif } } else if (!String.IsNullOrEmpty(ExecutePropertyName)) { // Get the property info and check the property type. PropertyInfo methodProperty = type.GetPropertyInfo(ExecutePropertyName); if (methodProperty == null) { List <Tuple <Type, object> > locatedViewModels = BindHelper.LocateAppendedViewModels(sourceBaseProvided); foreach (var model in locatedViewModels) { methodProperty = model.Item2.GetPropertyInfo(ExecutePropertyName); if (methodProperty != null) { sourceBaseProvided = model.Item2; type = model.Item1; break; } } } if ((methodProperty == null) || (methodProperty.PropertyType != typeof(Action <object>))) { throw new ArgumentException("BindCommandBase - cannot resolve 'ExecutePropertyName' property " + ExecuteMethodName); } executeDelegate = (Action <object>)methodProperty.GetValue(sourceBaseProvided, null); } if (!String.IsNullOrEmpty(CanExecuteBooleanPropertyName)) { PropertyInfo booleanProperty = type.GetPropertyInfo(CanExecuteBooleanPropertyName); if (booleanProperty == null) { List <Tuple <Type, object> > locatedViewModels = BindHelper.LocateAppendedViewModels(sourceBaseProvided); foreach (var model in locatedViewModels) { booleanProperty = model.Item2.GetPropertyInfo(CanExecuteBooleanPropertyName); if (booleanProperty != null) { sourceBaseProvided = model.Item2; type = model.Item1; break; } } } if ((booleanProperty == null) || (booleanProperty.PropertyType != typeof(Boolean))) { throw new ArgumentException("BindCommandBase - cannot resolve 'CanExecuteBooleanPropertyName' property " + CanExecuteBooleanPropertyName); } ResolvedCommand = WeakBinding ? new WeakCommandHandlerProxy(executeDelegate, booleanProperty, sourceBaseProvided) : new CommandHandlerProxy(executeDelegate, booleanProperty, sourceBaseProvided); return(ResolvedCommand); } if (!String.IsNullOrEmpty(CanExecuteMethodName)) { MethodInfo canExecuteMethod = type.GetMethodInfo(CanExecuteMethodName); if (canExecuteMethod == null) { List <Tuple <Type, object> > locatedViewModels = BindHelper.LocateAppendedViewModels(sourceBaseProvided); foreach (var model in locatedViewModels) { canExecuteMethod = model.Item2.GetMethodInfo(CanExecuteMethodName); if (canExecuteMethod != null) { sourceBaseProvided = model.Item2; type = model.Item1; break; } } } if (canExecuteMethod == null) { throw new ArgumentException("BindCommandBase - cannot resolve 'CanExecuteMethodName' method " + CanExecuteMethodName); } if (canExecuteMethod.IsStatic) { #if WINDOWS_UWP canExecuteDelegate = (Func <object, bool>)canExecuteMethod.CreateDelegate(typeof(Func <object, bool>)); #else canExecuteDelegate = (Func <object, bool>)Delegate.CreateDelegate(typeof(Func <object, bool>), canExecuteMethod); #endif } else { #if WINDOWS_UWP canExecuteDelegate = (Func <object, bool>)canExecuteMethod.CreateDelegate(typeof(Func <object, bool>), sourceBaseProvided); #else canExecuteDelegate = (Func <object, bool>)Delegate.CreateDelegate(typeof(Func <object, bool>), sourceBaseProvided, canExecuteMethod); #endif } } else if (!String.IsNullOrEmpty(CanExecutePropertyName)) { PropertyInfo methodProperty = type.GetPropertyInfo(CanExecutePropertyName); if (methodProperty == null) { List <Tuple <Type, object> > locatedViewModels = BindHelper.LocateAppendedViewModels(sourceBaseProvided); foreach (var model in locatedViewModels) { methodProperty = model.Item2.GetPropertyInfo(CanExecutePropertyName); if (methodProperty != null) { sourceBaseProvided = model.Item2; type = model.Item1; break; } } } if ((methodProperty == null) || (methodProperty.PropertyType != typeof(Func <object, bool>))) { throw new ArgumentException("BindCommandBase - cannot resolve 'CanExecutePropertyName' property " + CanExecuteMethodName); } canExecuteDelegate = (Func <object, bool>)methodProperty.GetValue(sourceBaseProvided, null); } if (!String.IsNullOrEmpty(EventToInvokeCanExecuteChanged)) { outerEvent = type.GetEventInfo(EventToInvokeCanExecuteChanged); if (outerEvent == null) { List <Tuple <Type, object> > locatedViewModels = BindHelper.LocateAppendedViewModels(sourceBaseProvided); foreach (var model in locatedViewModels) { outerEvent = model.Item2.GetEventInfo(EventToInvokeCanExecuteChanged); if (outerEvent != null) { sourceBaseProvided = model.Item2; type = model.Item1; break; } } } if (outerEvent == null) { throw new ArgumentException("BindCommandBase - cannot resolve 'EventToInvokeCanExecuteChanged' event " + EventToInvokeCanExecuteChanged); } } if (!String.IsNullOrEmpty(PropertyActionCanExecuteChanged)) { outerProperty = type.GetPropertyInfo(PropertyActionCanExecuteChanged); if (outerProperty == null) { List <Tuple <Type, object> > locatedViewModels = BindHelper.LocateAppendedViewModels(sourceBaseProvided); foreach (var model in locatedViewModels) { outerProperty = model.Item2.GetPropertyInfo(PropertyActionCanExecuteChanged); if (outerProperty != null) { sourceBaseProvided = model.Item2; type = model.Item1; break; } } } if (outerProperty == null) { throw new ArgumentException("BindCommandBase - cannot resolve 'PropertyActionCanExecuteChanged' property " + PropertyActionCanExecuteChanged); } } if ((outerEvent != null) || (outerProperty != null)) { if (outerEvent != null) { ResolvedCommand = WeakBinding ? new WeakCommandHandlerProxy(executeDelegate, canExecuteDelegate, outerEvent, sourceBaseProvided) : new CommandHandlerProxy(executeDelegate, canExecuteDelegate, outerEvent, sourceBaseProvided); } else if (outerProperty != null) { ResolvedCommand = WeakBinding ? new WeakCommandHandlerProxy(executeDelegate, canExecuteDelegate, outerProperty, sourceBaseProvided) : new CommandHandlerProxy(executeDelegate, canExecuteDelegate, outerProperty, sourceBaseProvided); } return(ResolvedCommand); } ResolvedCommand = WeakBinding ? new WeakCommandHandlerProxy(executeDelegate, canExecuteDelegate) : new CommandHandlerProxy(executeDelegate, canExecuteDelegate); return(ResolvedCommand); }
/// <summary> /// Validates an object if it is match to the type or/and members content. /// </summary> /// <param name="value">The object to validate.</param> /// <param name="methodName">The method name in the dependency property object. /// The properties will be scan up over the visual tree until the method name will be in math to the method in the object /// that represented by a property value.</param> /// <param name="propertyName">The property name in the dependency property object. /// The properties will be scan up over the visual tree until the property name will be in math to the property in the object /// that represented by a property value.</param> /// <param name="eventName">The event name in the dependency property object. /// The properties will be scan up over the visual tree until the event name will be in math to the event in the object /// that represented by a property value.</param> /// <param name="matchType">The type which should match with a property or event or method name or by it self.</param> /// <returns>Returns true if it has a match.</returns> static public bool ValidateValue(object value, string methodName, string propertyName = null, string eventName = null, Type matchType = null) { if (string.IsNullOrEmpty(methodName) && string.IsNullOrEmpty(propertyName) && string.IsNullOrEmpty(eventName) && matchType == null) { return(true); } if (string.IsNullOrEmpty(methodName) && string.IsNullOrEmpty(propertyName) && string.IsNullOrEmpty(eventName)) { #if WINDOWS_UWP return(value.GetType() == matchType || value.GetType().GetTypeInfo().IsSubclassOf(matchType)); #else return(value.GetType() == matchType || value.GetType().IsSubclassOf(matchType)); #endif } // Deep check the property object with the method name if (!string.IsNullOrEmpty(methodName)) { MethodInfo methodInfo = value.GetMethodInfo(methodName); if (methodInfo == null) { List <Tuple <Type, object> > locatedViewModels = BindHelper.LocateAppendedViewModels(value); foreach (var model in locatedViewModels) { methodInfo = model.Item2.GetMethodInfo(methodName); if (methodInfo != null) { break; } } } if (methodInfo != null) { if (matchType != null) { #if WINDOWS_UWP return(value.GetType() == matchType || value.GetType().GetTypeInfo().IsSubclassOf(matchType)); #else return(value.GetType() == matchType || value.GetType().IsSubclassOf(matchType)); #endif } // Return only if it has a math in the object return(true); } } // Deep check the property object with the property name if (!string.IsNullOrEmpty(propertyName)) { PropertyInfo propertyInfo = value.GetPropertyInfo(propertyName); if (propertyInfo == null) { List <Tuple <Type, object> > locatedViewModels = BindHelper.LocateAppendedViewModels(value); foreach (var model in locatedViewModels) { propertyInfo = model.Item2.GetPropertyInfo(propertyName); if (propertyInfo != null) { break; } } } if (propertyInfo != null) { if (matchType != null) { #if WINDOWS_UWP return(value.GetType() == matchType || value.GetType().GetTypeInfo().IsSubclassOf(matchType)); #else return(value.GetType() == matchType || value.GetType().IsSubclassOf(matchType)); #endif } // Return only if it has a math in the object return(true); } } // Deep check the property object with the event name if (!string.IsNullOrEmpty(eventName)) { EventInfo eventInfo = value.GetEventInfo(eventName); if (eventInfo == null) { List <Tuple <Type, object> > locatedViewModels = BindHelper.LocateAppendedViewModels(value); foreach (var model in locatedViewModels) { eventInfo = model.Item2.GetEventInfo(eventName); if (eventInfo != null) { break; } } } if (eventInfo != null) { if (matchType != null) { #if WINDOWS_UWP return(value.GetType() == matchType || value.GetType().GetTypeInfo().IsSubclassOf(matchType)); #else return(value.GetType() == matchType || value.GetType().IsSubclassOf(matchType)); #endif } // Return only if it has a math in the object return(true); } } return(false); }
/// <summary> /// Returns an object that should be set on the property where this extension is applied. /// </summary> /// <param name="serviceProvider">An object that can provide services for the markup extension.</param> /// <returns>The object value to set on the property where the markup extension provided value is evaluated.</returns> public override object ProvideValue(IServiceProvider serviceProvider) { // ReSharper disable SuggestUseVarKeywordEvident IProvideValueTarget valueTarget = serviceProvider.GetService(typeof(IProvideValueTarget)) as IProvideValueTarget; // ReSharper restore SuggestUseVarKeywordEvident if ((valueTarget != null) && (valueTarget.TargetObject != null) && (valueTarget.TargetProperty != null)) { TargetObject = valueTarget.TargetObject; TargetProperty = valueTarget.TargetProperty; } Type desiredDelegateType = typeof(RoutedEventHandler); #if !WINDOWS_UWP if ((valueTarget != null) && (valueTarget.TargetObject != null) && (valueTarget.TargetObject is FakeCollection) && (valueTarget.TargetProperty == null)) { // XAML WinRt doesn't call ProvideValue() but WPF always does call ProvideVlue() // WPF - for case of the FakeCollectionEventHandler as a target object returns the instance of the object. // WPF - will call the instance of this object to resolve event handler delegate return(this); } if ((valueTarget != null) && (valueTarget.TargetObject != null) && (valueTarget.TargetProperty == BindXAML.AddEventsProperty)) { throw new ArgumentException("BindEventHandlerBase - Coding Error Direct access to attached property XAML Parser."); } if ((valueTarget != null) && (valueTarget.TargetObject != null) && (valueTarget.TargetProperty != null) && (valueTarget.TargetProperty is MethodInfo)) { // Support for a single attached property for WPF // XAML WinRt doesn't call ProvideValue() but WPF always does call ProvideVlue() // In this case if use the single attached property we have to demonstrate // Extract desired type from add method (object, handler) MethodInfo mf = valueTarget.TargetProperty as MethodInfo; if (mf.GetParameters().Length == 2) { var pfs = mf.GetParameters(); desiredDelegateType = pfs[1].ParameterType; } else { return(this); } } else #endif if ((valueTarget != null) && (valueTarget.TargetObject != null) && (valueTarget.TargetProperty != null)) { if (!(valueTarget.TargetProperty is MethodInfo)) { // Should not be check if bind in style of attached property if (!(valueTarget.TargetProperty is EventInfo)) { throw new ArgumentException("BindEventHandlerBase - Target should be 'event' type class member"); } desiredDelegateType = (valueTarget.TargetProperty as EventInfo).EventHandlerType; } } if (BindHelper.IsInDesignModeStatic) { var info = this.GetMethodInfo("DesignRoutedEventHandler"); object designProvidedValue; if (info.IsStatic) { #if WINDOWS_UWP designProvidedValue = info.CreateDelegate(desiredDelegateType); #else designProvidedValue = Delegate.CreateDelegate(desiredDelegateType, info); #endif } else { #if WINDOWS_UWP designProvidedValue = info.CreateDelegate(desiredDelegateType, this); #else designProvidedValue = Delegate.CreateDelegate(desiredDelegateType, this, info); #endif } // Cannot correctly resolve in the design mode the source. return(designProvidedValue); } object sourceBaseProvided = ObtainSourceObject(serviceProvider); if ((!String.IsNullOrEmpty(PropertyName)) && (!String.IsNullOrEmpty(MethodName))) { throw new ArgumentException("BindEventHandlerBase - Should be set only one property 'MethodName' or 'PropertyName'"); } if ((String.IsNullOrEmpty(PropertyName)) && (String.IsNullOrEmpty(MethodName))) { throw new ArgumentException("BindEventHandlerBase - Should be set one of properties 'MethodName' or 'PropertyName'"); } if (!String.IsNullOrEmpty(PropertyName)) { if (sourceBaseProvided == null) { if (this is BindEventHandler) { // Set the loaded event and requested event because we don't know which is going to be called first ResolvedEventHandler = DataContextProxyRoutedEventHandler.CreateProxyDelegate(desiredDelegateType, MethodName, PropertyName); } else { throw new ArgumentException("BindEventHandlerBase - cannot resolve 'PropertyName' property " + PropertyName); } } else { var propertyInfo = sourceBaseProvided.GetPropertyInfo(PropertyName); if (propertyInfo == null) { List <Tuple <Type, object> > locatedViewModels = BindHelper.LocateAppendedViewModels(sourceBaseProvided); foreach (var model in locatedViewModels) { propertyInfo = model.Item2.GetPropertyInfo(PropertyName); if (propertyInfo != null) { sourceBaseProvided = model.Item2; break; } } } if (propertyInfo == null) { throw new ArgumentException("BindEventHandlerBase - cannot resolve 'PropertyName' property " + PropertyName); } ResolvedEventHandler = propertyInfo.GetValue(sourceBaseProvided, null); } } if (!String.IsNullOrEmpty(MethodName)) { if (sourceBaseProvided == null) { if (this is BindEventHandler) { // Set the loaded event and requested event because we don't know which is going to be called first ResolvedEventHandler = DataContextProxyRoutedEventHandler.CreateProxyDelegate(desiredDelegateType, MethodName, PropertyName); } else { throw new ArgumentException("BindEventHandlerBase - cannot resolve 'MethodName' property " + MethodName); } } else { //Get all appenders MethodInfo methodInfo = sourceBaseProvided.GetMethodInfo(MethodName); if (methodInfo == null) { List <Tuple <Type, object> > locatedViewModels = BindHelper.LocateAppendedViewModels(sourceBaseProvided); foreach (var model in locatedViewModels) { methodInfo = model.Item2.GetMethodInfo(MethodName); if (methodInfo != null) { sourceBaseProvided = model.Item2; break; } } } if (methodInfo == null) { throw new ArgumentException("BindEventHandlerBase - cannot resolve 'MethodName' property " + MethodName); } if (methodInfo.IsStatic) { #if WINDOWS_UWP ResolvedEventHandler = methodInfo.CreateDelegate(desiredDelegateType); #else ResolvedEventHandler = Delegate.CreateDelegate(desiredDelegateType, methodInfo); #endif } else { #if WINDOWS_UWP ResolvedEventHandler = methodInfo.CreateDelegate(desiredDelegateType, sourceBaseProvided); #else ResolvedEventHandler = Delegate.CreateDelegate(desiredDelegateType, sourceBaseProvided, methodInfo); #endif } } } return(ResolvedEventHandler); }