Applying same interaction trigger to multiple TextBoxes

前端 未结 2 1664
北恋
北恋 2021-01-24 07:57

I have multiple textboxes bound to different data, but I would like every one to launch the same command when the TextChanged event is fired. I could copy the interaction line u

2条回答
  •  孤街浪徒
    2021-01-24 08:32

    I'm not positive how to do it with Interaction.Triggers, but in the past I've used the AttachedCommand dependency properties found here and simply used a Style

    Normal XAML

    
    

    Using a Style

    
    

    EDIT: Since you can't download files at work, here's the code

    CommandBehavior.cs

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Windows.Markup;
    using System.Windows;
    using System.Windows.Input;
    
    // Code to attach a command to any event
    // From http://marlongrech.wordpress.com/2008/12/04/attachedcommandbehavior-aka-acb/
    namespace Keys.Controls.Helpers.CommandHelpers
    {
        /// 
        /// Defines the attached properties to create a CommandBehaviorBinding
        /// 
        public class CommandBehavior
        {
            #region Behavior
    
            /// 
            /// Behavior Attached Dependency Property
            /// 
            private static readonly DependencyProperty BehaviorProperty =
                DependencyProperty.RegisterAttached("Behavior", typeof(CommandBehaviorBinding), typeof(CommandBehavior),
                    new FrameworkPropertyMetadata((CommandBehaviorBinding)null));
    
            /// 
            /// Gets the Behavior property. 
            /// 
            private static CommandBehaviorBinding GetBehavior(DependencyObject d)
            {
                return (CommandBehaviorBinding)d.GetValue(BehaviorProperty);
            }
    
            /// 
            /// Sets the Behavior property.  
            /// 
            private static void SetBehavior(DependencyObject d, CommandBehaviorBinding value)
            {
                d.SetValue(BehaviorProperty, value);
            }
    
            #endregion
    
            #region Command
    
            /// 
            /// Command Attached Dependency Property
            /// 
            public static readonly DependencyProperty CommandProperty =
                DependencyProperty.RegisterAttached("Command", typeof(ICommand), typeof(CommandBehavior),
                    new FrameworkPropertyMetadata((ICommand)null,
                        new PropertyChangedCallback(OnCommandChanged)));
    
            /// 
            /// Gets the Command property.  
            /// 
            public static ICommand GetCommand(DependencyObject d)
            {
                return (ICommand)d.GetValue(CommandProperty);
            }
    
            /// 
            /// Sets the Command property. 
            /// 
            public static void SetCommand(DependencyObject d, ICommand value)
            {
                d.SetValue(CommandProperty, value);
            }
    
            /// 
            /// Handles changes to the Command property.
            /// 
            private static void OnCommandChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
            {
                CommandBehaviorBinding binding = FetchOrCreateBinding(d);
                binding.Command = (ICommand)e.NewValue;
            }
    
            #endregion
    
            #region CommandParameter
    
            /// 
            /// CommandParameter Attached Dependency Property
            /// 
            public static readonly DependencyProperty CommandParameterProperty =
                DependencyProperty.RegisterAttached("CommandParameter", typeof(object), typeof(CommandBehavior),
                    new FrameworkPropertyMetadata((object)null,
                        new PropertyChangedCallback(OnCommandParameterChanged)));
    
            /// 
            /// Gets the CommandParameter property.  
            /// 
            public static object GetCommandParameter(DependencyObject d)
            {
                return (object)d.GetValue(CommandParameterProperty);
            }
    
            /// 
            /// Sets the CommandParameter property. 
            /// 
            public static void SetCommandParameter(DependencyObject d, object value)
            {
                d.SetValue(CommandParameterProperty, value);
            }
    
            /// 
            /// Handles changes to the CommandParameter property.
            /// 
            private static void OnCommandParameterChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
            {
                CommandBehaviorBinding binding = FetchOrCreateBinding(d);
                binding.CommandParameter = e.NewValue;
            }
    
            #endregion
    
            #region Event
    
            /// 
            /// Event Attached Dependency Property
            /// 
            public static readonly DependencyProperty EventProperty =
                DependencyProperty.RegisterAttached("Event", typeof(string), typeof(CommandBehavior),
                    new FrameworkPropertyMetadata((string)String.Empty,
                        new PropertyChangedCallback(OnEventChanged)));
    
            /// 
            /// Gets the Event property.  This dependency property 
            /// indicates ....
            /// 
            public static string GetEvent(DependencyObject d)
            {
                return (string)d.GetValue(EventProperty);
            }
    
            /// 
            /// Sets the Event property.  This dependency property 
            /// indicates ....
            /// 
            public static void SetEvent(DependencyObject d, string value)
            {
                d.SetValue(EventProperty, value);
            }
    
            /// 
            /// Handles changes to the Event property.
            /// 
            private static void OnEventChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
            {
                CommandBehaviorBinding binding = FetchOrCreateBinding(d);
                //check if the Event is set. If yes we need to rebind the Command to the new event and unregister the old one
                if (binding.Event != null && binding.Owner != null)
                    binding.Dispose();
                //bind the new event to the command if newValue isn't blank (e.g. switching tabs)
                if (e.NewValue.ToString() != "")
                    binding.BindEvent(d, e.NewValue.ToString());
            }
    
            #endregion
    
            #region Helpers
            //tries to get a CommandBehaviorBinding from the element. Creates a new instance if there is not one attached
            private static CommandBehaviorBinding FetchOrCreateBinding(DependencyObject d)
            {
                CommandBehaviorBinding binding = CommandBehavior.GetBehavior(d);
                if (binding == null)
                {
                    binding = new CommandBehaviorBinding();
                    CommandBehavior.SetBehavior(d, binding);
                }
                return binding;
            }
            #endregion
    
        }
    
    }
    

    CommandBehaviorBinding.cs

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Windows.Input;
    using System.Reflection;
    using System.Windows;
    
    // Code to attach a command to any event
    // From http://marlongrech.wordpress.com/2008/12/04/attachedcommandbehavior-aka-acb/
    namespace Keys.Controls.Helpers.CommandHelpers
    {
        /// 
        /// Defines the command behavior binding
        /// 
        public class CommandBehaviorBinding : IDisposable
        {
            #region Properties
            /// 
            /// Get the owner of the CommandBinding ex: a Button
            /// This property can only be set from the BindEvent Method
            /// 
            public DependencyObject Owner { get; private set; }
            /// 
            /// The command to execute when the specified event is raised
            /// 
            public ICommand Command { get; set; }
            /// 
            /// Gets or sets a CommandParameter
            /// 
            public object CommandParameter { get; set; }
            /// 
            /// The event name to hook up to
            /// This property can only be set from the BindEvent Method
            /// 
            public string EventName { get; private set; }
            /// 
            /// The event info of the event
            /// 
            public EventInfo Event { get; private set; }
            /// 
            /// Gets the EventHandler for the binding with the event
            /// 
            public Delegate EventHandler { get; private set; }
    
            #endregion
    
            //Creates an EventHandler on runtime and registers that handler to the Event specified
            public void BindEvent(DependencyObject owner, string eventName)
            {
                EventName = eventName;
                Owner = owner;
                Event = Owner.GetType().GetEvent(EventName, BindingFlags.Public | BindingFlags.Instance);
                if (Event == null)
                    throw new InvalidOperationException(String.Format("Could not resolve event name {0}", EventName));
    
                //Create an event handler for the event that will call the ExecuteCommand method
                EventHandler = EventHandlerGenerator.CreateDelegate(
                    Event.EventHandlerType, typeof(CommandBehaviorBinding).GetMethod("ExecuteCommand", BindingFlags.Public | BindingFlags.Instance), this);
                //Register the handler to the Event
                Event.AddEventHandler(Owner, EventHandler);
            }
    
            /// 
            /// Executes the command
            /// 
            public void ExecuteCommand()
            {
                if (Command != null && Command.CanExecute(CommandParameter))
                    Command.Execute(CommandParameter);
            }
    
            #region IDisposable Members
            bool disposed = false;
            /// 
            /// Unregisters the EventHandler from the Event
            /// 
            public void Dispose()
            {
                if (!disposed)
                {
                    Event.RemoveEventHandler(Owner, EventHandler);
                    disposed = true;
                }
            }
    
            #endregion
        }
    }
    

    EventHandlerGenerator.cs

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Reflection.Emit;
    using System.Reflection;
    
    // Code to attach a command to any event
    // From http://marlongrech.wordpress.com/2008/12/04/attachedcommandbehavior-aka-acb/
    namespace Keys.Controls.Helpers.CommandHelpers
    {
        /// 
        /// Generates delegates according to the specified signature on runtime
        /// 
        public static class EventHandlerGenerator
        {
            /// 
            /// Generates a delegate with a matching signature of the supplied eventHandlerType
            /// This method only supports Events that have a delegate of type void
            /// 
            /// The delegate type to wrap. Note that this must always be a void delegate
            /// The method to invoke
            /// The object where the method resides
            /// Returns a delegate with the same signature as eventHandlerType that calls the methodToInvoke inside
            public static Delegate CreateDelegate(Type eventHandlerType, MethodInfo methodToInvoke, object methodInvoker)
            {
                //Get the eventHandlerType signature
                var eventHandlerInfo = eventHandlerType.GetMethod("Invoke");
                Type returnType = eventHandlerInfo.ReturnParameter.ParameterType;
                if (returnType != typeof(void))
                    throw new ApplicationException("Delegate has a return type. This only supprts event handlers that are void");
    
                ParameterInfo[] delegateParameters = eventHandlerInfo.GetParameters();
                //Get the list of type of parameters. Please note that we do + 1 because we have to push the object where the method resides i.e methodInvoker parameter
                Type[] hookupParameters = new Type[delegateParameters.Length + 1];
                hookupParameters[0] = methodInvoker.GetType();
                for (int i = 0; i < delegateParameters.Length; i++)
                    hookupParameters[i + 1] = delegateParameters[i].ParameterType;
    
                DynamicMethod handler = new DynamicMethod("", null,
                    hookupParameters, typeof(EventHandlerGenerator));
    
                ILGenerator eventIL = handler.GetILGenerator();
    
                //load the parameters or everything will just BAM :)
                LocalBuilder local = eventIL.DeclareLocal(typeof(object[]));
                eventIL.Emit(OpCodes.Ldc_I4, delegateParameters.Length + 1);
                eventIL.Emit(OpCodes.Newarr, typeof(object));
                eventIL.Emit(OpCodes.Stloc, local);
    
                //start from 1 because the first item is the instance. Load up all the arguments
                for (int i = 1; i < delegateParameters.Length + 1; i++)
                {
                    eventIL.Emit(OpCodes.Ldloc, local);
                    eventIL.Emit(OpCodes.Ldc_I4, i);
                    eventIL.Emit(OpCodes.Ldarg, i);
                    eventIL.Emit(OpCodes.Stelem_Ref);
                }
    
                eventIL.Emit(OpCodes.Ldloc, local);
    
                //Load as first argument the instance of the object for the methodToInvoke i.e methodInvoker
                eventIL.Emit(OpCodes.Ldarg_0);
    
                //Now that we have it all set up call the actual method that we want to call for the binding
                eventIL.EmitCall(OpCodes.Call, methodToInvoke, null);
    
                eventIL.Emit(OpCodes.Pop);
                eventIL.Emit(OpCodes.Ret);
    
                //create a delegate from the dynamic method
                return handler.CreateDelegate(eventHandlerType, methodInvoker);
            }
    
        }
    }
    

提交回复
热议问题