• WPF Custom Command And Binding


      1 using System;
      2 using System.Collections.Generic;
      3 using System.Windows.Input;
      4 
      5 namespace WPF.Commands
      6 {
      7   /// <summary>
      8   ///     This class allows delegating the commanding logic to methods passed as parameters,
      9   ///     and enables a View to bind commands to objects that are not part of the element tree.
     10   /// </summary>
     11   public class DelegateCommand : ICommand
     12   {
     13     #region Constructors
     14 
     15     /// <summary>
     16     /// Constructor
     17     /// </summary>
     18     public DelegateCommand(Action executeMethod)
     19         : this(executeMethod, null, false)
     20     {
     21     }
     22 
     23     /// <summary>
     24     ///     Constructor
     25     /// </summary>
     26     public DelegateCommand(Action executeMethod, Func<bool> canExecuteMethod)
     27         : this(executeMethod, canExecuteMethod, false)
     28     {
     29     }
     30 
     31     /// <summary>
     32     ///     Constructor
     33     /// </summary>
     34     public DelegateCommand(Action executeMethod, Func<bool> canExecuteMethod, bool isAutomaticRequeryDisabled)
     35     {
     36       if (executeMethod == null)
     37       {
     38         throw new ArgumentNullException("executeMethod");
     39       }
     40 
     41       _executeMethod = executeMethod;
     42       _canExecuteMethod = canExecuteMethod;
     43       _isAutomaticRequeryDisabled = isAutomaticRequeryDisabled;
     44     }
     45 
     46     #endregion
     47 
     48     #region Public Methods
     49 
     50     /// <summary>
     51     ///     Method to determine if the command can be executed
     52     /// </summary>
     53     public bool CanExecute()
     54     {
     55       if (_canExecuteMethod != null)
     56       {
     57         return _canExecuteMethod();
     58       }
     59       return true;
     60     }
     61 
     62     /// <summary>
     63     ///     Execution of the command
     64     /// </summary>
     65     public void Execute()
     66     {
     67       if (_executeMethod != null)
     68       {
     69         _executeMethod();
     70       }
     71     }
     72 
     73     /// <summary>
     74     ///     Property to enable or disable CommandManager's automatic requery on this command
     75     /// </summary>
     76     public bool IsAutomaticRequeryDisabled
     77     {
     78       get
     79       {
     80         return _isAutomaticRequeryDisabled;
     81       }
     82       set
     83       {
     84         if (_isAutomaticRequeryDisabled != value)
     85         {
     86           if (value)
     87           {
     88             CommandManagerHelper.RemoveHandlersFromRequerySuggested(_canExecuteChangedHandlers);
     89           }
     90           else
     91           {
     92             CommandManagerHelper.AddHandlersToRequerySuggested(_canExecuteChangedHandlers);
     93           }
     94           _isAutomaticRequeryDisabled = value;
     95         }
     96       }
     97     }
     98 
     99     /// <summary>
    100     ///     Raises the CanExecuteChaged event
    101     /// </summary>
    102     public void RaiseCanExecuteChanged()
    103     {
    104       OnCanExecuteChanged();
    105     }
    106 
    107     /// <summary>
    108     ///     Protected virtual method to raise CanExecuteChanged event
    109     /// </summary>
    110     protected virtual void OnCanExecuteChanged()
    111     {
    112       CommandManagerHelper.CallWeakReferenceHandlers(_canExecuteChangedHandlers);
    113     }
    114 
    115     #endregion
    116 
    117     #region ICommand Members
    118 
    119     /// <summary>
    120     /// ICommand.CanExecuteChanged implementation
    121     /// </summary>
    122     public event EventHandler CanExecuteChanged
    123     {
    124       add
    125       {
    126         if (!_isAutomaticRequeryDisabled)
    127         {
    128           CommandManager.RequerySuggested += value;
    129         }
    130         CommandManagerHelper.AddWeakReferenceHandler(ref _canExecuteChangedHandlers, value, 2);
    131       }
    132       remove
    133       {
    134         if (!_isAutomaticRequeryDisabled)
    135         {
    136           CommandManager.RequerySuggested -= value;
    137         }
    138         CommandManagerHelper.RemoveWeakReferenceHandler(_canExecuteChangedHandlers, value);
    139       }
    140     }
    141 
    142     /// <summary>
    143     /// 
    144     /// </summary>
    145     /// <param name="parameter"></param>
    146     /// <returns></returns>
    147     bool ICommand.CanExecute(object parameter)
    148     {
    149       return CanExecute();
    150     }
    151 
    152     /// <summary>
    153     /// 
    154     /// </summary>
    155     /// <param name="parameter"></param>
    156     void ICommand.Execute(object parameter)
    157     {
    158       Execute();
    159     }
    160 
    161     #endregion
    162 
    163     #region Data
    164     /// <summary>
    165     /// 
    166     /// </summary>
    167     private readonly Action _executeMethod = null;
    168     /// <summary>
    169     /// 
    170     /// </summary>
    171     private readonly Func<bool> _canExecuteMethod = null;
    172     /// <summary>
    173     /// 
    174     /// </summary>
    175     private bool _isAutomaticRequeryDisabled = false;
    176     /// <summary>
    177     /// 
    178     /// </summary>
    179     private List<WeakReference> _canExecuteChangedHandlers;
    180 
    181     #endregion
    182   }
    183 
    184   /// <summary>
    185   ///     This class allows delegating the commanding logic to methods passed as parameters,
    186   ///     and enables a View to bind commands to objects that are not part of the element tree.
    187   /// </summary>
    188   /// <typeparam name="TExecuteParameter">Type of the parameter passed to the delegates</typeparam>
    189   public class DelegateCommand<TExecuteParameter> : ICommand
    190   {
    191     #region Constructors
    192 
    193     /// <summary>
    194     ///     Constructor
    195     /// </summary>
    196     public DelegateCommand(Action<TExecuteParameter> onExecute)
    197         : this(onExecute, null, false)
    198     {
    199     }
    200 
    201     /// <summary>
    202     ///     Constructor
    203     /// </summary>
    204     public DelegateCommand(Action<TExecuteParameter> onExecute, Func<TExecuteParameter, bool> canExecute)
    205         : this(onExecute, canExecute, false)
    206     {
    207     }
    208 
    209     /// <summary>
    210     ///     Constructor
    211     /// </summary>
    212     public DelegateCommand(Action<TExecuteParameter> onExecute, Func<TExecuteParameter, bool> canExecute, bool isAutomaticRequeryDisabled)
    213     {
    214       if (onExecute == null)
    215       {
    216         throw new ArgumentNullException("executeMethod");
    217       }
    218       _onExecute = onExecute;
    219       _canExecute = canExecute;
    220       _isAutomaticRequeryDisabled = isAutomaticRequeryDisabled;
    221     }
    222 
    223     #endregion
    224 
    225     #region Public Methods
    226 
    227     /// <summary>
    228     ///     Method to determine if the command can be executed
    229     /// </summary>
    230     public bool CanExecute(TExecuteParameter parameter)
    231     {
    232       if (_canExecute != null)
    233       {
    234         return _canExecute(parameter);
    235       }
    236       return true;
    237     }
    238 
    239     /// <summary>
    240     ///     Execution of the command
    241     /// </summary>
    242     public void Execute(TExecuteParameter parameter)
    243     {
    244       if (_onExecute != null)
    245       {
    246         _onExecute(parameter);
    247       }
    248     }
    249 
    250     /// <summary>
    251     ///     Raises the CanExecuteChaged event
    252     /// </summary>
    253     public void RaiseCanExecuteChanged()
    254     {
    255       OnCanExecuteChanged();
    256     }
    257 
    258     /// <summary>
    259     ///     Protected virtual method to raise CanExecuteChanged event
    260     /// </summary>
    261     protected virtual void OnCanExecuteChanged()
    262     {
    263       CommandManagerHelper.CallWeakReferenceHandlers(_canExecuteChangedHandlers);
    264     }
    265 
    266     /// <summary>
    267     ///     Property to enable or disable CommandManager's automatic requery on this command
    268     /// </summary>
    269     public bool IsAutomaticRequeryDisabled
    270     {
    271       get
    272       {
    273         return _isAutomaticRequeryDisabled;
    274       }
    275       set
    276       {
    277         if (_isAutomaticRequeryDisabled != value)
    278         {
    279           if (value)
    280           {
    281             CommandManagerHelper.RemoveHandlersFromRequerySuggested(_canExecuteChangedHandlers);
    282           }
    283           else
    284           {
    285             CommandManagerHelper.AddHandlersToRequerySuggested(_canExecuteChangedHandlers);
    286           }
    287           _isAutomaticRequeryDisabled = value;
    288         }
    289       }
    290     }
    291 
    292     #endregion
    293 
    294     #region ICommand Members
    295 
    296     /// <summary>
    297     ///     ICommand.CanExecuteChanged implementation
    298     /// </summary>
    299     public event EventHandler CanExecuteChanged
    300     {
    301       add
    302       {
    303         if (!_isAutomaticRequeryDisabled)
    304         {
    305           CommandManager.RequerySuggested += value;
    306         }
    307         CommandManagerHelper.AddWeakReferenceHandler(ref _canExecuteChangedHandlers, value, 2);
    308       }
    309       remove
    310       {
    311         if (!_isAutomaticRequeryDisabled)
    312         {
    313           CommandManager.RequerySuggested -= value;
    314         }
    315         CommandManagerHelper.RemoveWeakReferenceHandler(_canExecuteChangedHandlers, value);
    316       }
    317     }
    318 
    319     /// <summary>
    320     /// 
    321     /// </summary>
    322     /// <param name="parameter"></param>
    323     /// <returns></returns>
    324     bool ICommand.CanExecute(object parameter)
    325     {
    326       // if T is of value type and the parameter is not
    327       // set yet, then return false if CanExecute delegate
    328       // exists, else return true
    329       var type = typeof(TExecuteParameter);
    330       if (type.IsValueType && type.IsPrimitive)
    331       {
    332         if (int.TryParse(parameter.ToString(), out int intResult))
    333         {
    334           return CanExecute((TExecuteParameter)(object)intResult);
    335         }
    336       }
    337 
    338       if (parameter == null && type.IsValueType)
    339       {
    340         return (_canExecute == null);
    341       }
    342       return CanExecute((TExecuteParameter)parameter);
    343     }
    344 
    345     /// <summary>
    346     /// 
    347     /// </summary>
    348     /// <param name="parameter"></param>
    349     void ICommand.Execute(object parameter)
    350     {
    351       Execute((TExecuteParameter)parameter);
    352     }
    353 
    354     #endregion
    355 
    356     #region Data
    357     /// <summary>
    358     /// 
    359     /// </summary>
    360     private readonly Action<TExecuteParameter> _onExecute = null;
    361     /// <summary>
    362     /// 
    363     /// </summary>
    364     private readonly Func<TExecuteParameter, bool> _canExecute = null;
    365     /// <summary>
    366     /// 
    367     /// </summary>
    368     private bool _isAutomaticRequeryDisabled = false;
    369     /// <summary>
    370     /// 
    371     /// </summary>
    372     private List<WeakReference> _canExecuteChangedHandlers;
    373 
    374     #endregion
    375   }
    376 
    377   /// <summary>
    378   ///     This class contains methods for the CommandManager that help avoid memory leaks by
    379   ///     using weak references.
    380   /// </summary>
    381   internal class CommandManagerHelper
    382   {
    383     internal static void CallWeakReferenceHandlers(List<WeakReference> handlers)
    384     {
    385       if (handlers != null)
    386       {
    387         // Take a snapshot of the handlers before we call out to them since the handlers
    388         // could cause the array to me modified while we are reading it.
    389 
    390         EventHandler[] callees = new EventHandler[handlers.Count];
    391         int count = 0;
    392 
    393         for (int i = handlers.Count - 1; i >= 0; i--)
    394         {
    395           WeakReference reference = handlers[i];
    396           EventHandler handler = reference.Target as EventHandler;
    397           if (handler == null)
    398           {
    399             // Clean up old handlers that have been collected
    400             handlers.RemoveAt(i);
    401           }
    402           else
    403           {
    404             callees[count] = handler;
    405             count++;
    406           }
    407         }
    408 
    409         // Call the handlers that we snapshotted
    410         for (int i = 0; i < count; i++)
    411         {
    412           EventHandler handler = callees[i];
    413           handler(null, EventArgs.Empty);
    414         }
    415       }
    416     }
    417 
    418     /// <summary>
    419     /// 
    420     /// </summary>
    421     /// <param name="handlers"></param>
    422     internal static void AddHandlersToRequerySuggested(List<WeakReference> handlers)
    423     {
    424       if (handlers != null)
    425       {
    426         foreach (WeakReference handlerRef in handlers)
    427         {
    428           EventHandler handler = handlerRef.Target as EventHandler;
    429           if (handler != null)
    430           {
    431             CommandManager.RequerySuggested += handler;
    432           }
    433         }
    434       }
    435     }
    436 
    437     /// <summary>
    438     /// 
    439     /// </summary>
    440     /// <param name="handlers"></param>
    441     internal static void RemoveHandlersFromRequerySuggested(List<WeakReference> handlers)
    442     {
    443       if (handlers != null)
    444       {
    445         foreach (WeakReference handlerRef in handlers)
    446         {
    447           EventHandler handler = handlerRef.Target as EventHandler;
    448           if (handler != null)
    449           {
    450             CommandManager.RequerySuggested -= handler;
    451           }
    452         }
    453       }
    454     }
    455 
    456     /// <summary>
    457     /// 
    458     /// </summary>
    459     /// <param name="handlers"></param>
    460     /// <param name="handler"></param>
    461     internal static void AddWeakReferenceHandler(ref List<WeakReference> handlers, EventHandler handler)
    462     {
    463       AddWeakReferenceHandler(ref handlers, handler, -1);
    464     }
    465 
    466     /// <summary>
    467     /// 
    468     /// </summary>
    469     /// <param name="handlers"></param>
    470     /// <param name="handler"></param>
    471     /// <param name="defaultListSize"></param>
    472     internal static void AddWeakReferenceHandler(ref List<WeakReference> handlers, EventHandler handler, int defaultListSize)
    473     {
    474       if (handlers == null)
    475       {
    476         handlers = (defaultListSize > 0 ? new List<WeakReference>(defaultListSize) : new List<WeakReference>());
    477       }
    478 
    479       handlers.Add(new WeakReference(handler));
    480     }
    481 
    482     /// <summary>
    483     /// 
    484     /// </summary>
    485     /// <param name="handlers"></param>
    486     /// <param name="handler"></param>
    487     internal static void RemoveWeakReferenceHandler(List<WeakReference> handlers, EventHandler handler)
    488     {
    489       if (handlers != null)
    490       {
    491         for (int i = handlers.Count - 1; i >= 0; i--)
    492         {
    493           WeakReference reference = handlers[i];
    494           EventHandler existingHandler = reference.Target as EventHandler;
    495           if ((existingHandler == null) || (existingHandler == handler))
    496           {
    497             // Clean up old handlers that have been collected
    498             // in addition to the handler that is to be removed.
    499             handlers.RemoveAt(i);
    500           }
    501         }
    502       }
    503     }
    504   }
    505 }
    1 <Button Width="60"
    2             Height="30"
    3             DataContext="{Binding RelativeSource={RelativeSource AncestorType=Window}}"
    4             Command="{Binding TestCommand}"
    5             CommandParameter="123">Test</Button>
  • 相关阅读:
    2018-8-10-win10-uwp-重启软件
    jquery动画滑入滑出
    jquery类操作
    jquery类操作
    jquery手风琴
    jquery突出显示
    jquery隔行变色
    jquery下拉菜单
    jquery筛选选择器
    jquery过滤选择器
  • 原文地址:https://www.cnblogs.com/redleaf-me/p/8571288.html
Copyright © 2020-2023  润新知