using Microsoft.Xaml.Behaviors; using System; using System.Collections.Generic; using System.Globalization; using System.Linq; using System.Reflection; using System.Text; using System.Threading.Tasks; using System.Windows.Data; using System.Windows.Input; using System.Windows; namespace PDF_Master.Helper { public class CompositeCommandParameter { public CompositeCommandParameter(EventArgs eventArgs, object parameter) { EventArgs = eventArgs; Parameter = parameter; } public EventArgs EventArgs { get; } public object Parameter { get; } } public sealed class AdvancedInvokeCommandAction : TriggerAction { private string commandName; public static readonly DependencyProperty CommandProperty = DependencyProperty.Register("Command", typeof(ICommand), typeof(AdvancedInvokeCommandAction), null); public static readonly DependencyProperty CommandParameterProperty = DependencyProperty.Register("CommandParameter", typeof(object), typeof(AdvancedInvokeCommandAction), null); public static readonly DependencyProperty EventArgsConverterProperty = DependencyProperty.Register("EventArgsConverter", typeof(IValueConverter), typeof(AdvancedInvokeCommandAction), new PropertyMetadata(null)); public static readonly DependencyProperty EventArgsConverterParameterProperty = DependencyProperty.Register("EventArgsConverterParameter", typeof(object), typeof(AdvancedInvokeCommandAction), new PropertyMetadata(null)); public static readonly DependencyProperty EventArgsParameterPathProperty = DependencyProperty.Register("EventArgsParameterPath", typeof(string), typeof(AdvancedInvokeCommandAction), new PropertyMetadata(null)); /// /// Gets or sets the name of the command this action should invoke. /// /// The name of the command this action should invoke. /// This property will be superseded by the Command property if both are set. public string CommandName { get { this.ReadPreamble(); return this.commandName; } set { if (this.CommandName != value) { this.WritePreamble(); this.commandName = value; this.WritePostscript(); } } } /// /// Gets or sets the command this action should invoke. This is a dependency property. /// /// The command to execute. /// This property will take precedence over the CommandName property if both are set. public ICommand Command { get { return (ICommand)this.GetValue(CommandProperty); } set { this.SetValue(CommandProperty, value); } } /// /// Gets or sets the command parameter. This is a dependency property. /// /// The command parameter. /// This is the value passed to ICommand.CanExecute and ICommand.Execute. public object CommandParameter { get { return this.GetValue(AdvancedInvokeCommandAction.CommandParameterProperty); } set { this.SetValue(AdvancedInvokeCommandAction.CommandParameterProperty, value); } } /// /// Gets or sets the IValueConverter that is used to convert the EventArgs passed to the Command as a parameter. /// /// If the or properties are set, this property is ignored. public IValueConverter EventArgsConverter { get { return (IValueConverter)GetValue(EventArgsConverterProperty); } set { SetValue(EventArgsConverterProperty, value); } } /// /// Gets or sets the parameter that is passed to the EventArgsConverter. /// public object EventArgsConverterParameter { get { return (object)GetValue(EventArgsConverterParameterProperty); } set { SetValue(EventArgsConverterParameterProperty, value); } } /// /// Gets or sets the parameter path used to extract a value from an property to pass to the Command as a parameter. /// /// If the propert is set, this property is ignored. public string EventArgsParameterPath { get { return (string)GetValue(EventArgsParameterPathProperty); } set { SetValue(EventArgsParameterPathProperty, value); } } /// /// Specifies whether the EventArgs of the event that triggered this action should be passed to the Command as a parameter. /// /// If the , , or properties are set, this property is ignored. public bool PassEventArgsToCommand { get; set; } /// /// Invokes the action. /// /// The parameter to the action. If the action does not require a parameter, the parameter may be set to a null reference. protected override void Invoke(object parameter) { if (this.AssociatedObject != null) { ICommand command = this.ResolveCommand(); if (command != null) { object eventArgs = null; object commandParameter = this.CommandParameter; //if no CommandParameter has been provided, let's check the EventArgsParameterPath if (!string.IsNullOrWhiteSpace(this.EventArgsParameterPath)) { eventArgs = GetEventArgsPropertyPathValue(parameter); } //next let's see if an event args converter has been supplied if (eventArgs == null && this.EventArgsConverter != null) { eventArgs = this.EventArgsConverter.Convert(parameter, typeof(object), EventArgsConverterParameter, CultureInfo.CurrentCulture); } //last resort, let see if they want to force the event args to be passed as a parameter if (eventArgs == null && this.PassEventArgsToCommand) { eventArgs = parameter; } if (command.CanExecute(commandParameter)) { var compositeCommandParameter = new CompositeCommandParameter((EventArgs)eventArgs, commandParameter); command.Execute(compositeCommandParameter); } } } } private object GetEventArgsPropertyPathValue(object parameter) { object commandParameter; object propertyValue = parameter; string[] propertyPathParts = EventArgsParameterPath.Split('.'); foreach (string propertyPathPart in propertyPathParts) { PropertyInfo propInfo = propertyValue.GetType().GetProperty(propertyPathPart); propertyValue = propInfo.GetValue(propertyValue, null); } commandParameter = propertyValue; return commandParameter; } private ICommand ResolveCommand() { ICommand command = null; if (this.Command != null) { command = this.Command; } else if (this.AssociatedObject != null) { // todo jekelly 06/09/08: we could potentially cache some or all of this information if needed, updating when AssociatedObject changes Type associatedObjectType = this.AssociatedObject.GetType(); PropertyInfo[] typeProperties = associatedObjectType.GetProperties(BindingFlags.Public | BindingFlags.Instance); foreach (PropertyInfo propertyInfo in typeProperties) { if (typeof(ICommand).IsAssignableFrom(propertyInfo.PropertyType)) { if (string.Equals(propertyInfo.Name, this.CommandName, StringComparison.Ordinal)) { command = (ICommand)propertyInfo.GetValue(this.AssociatedObject, null); } } } } return command; } } }