using System;
using System.Collections.Generic;
using System.Windows.Input; namespace WPF.Commands
{
/// <summary>
/// This class allows delegating the commanding logic to methods passed as parameters,
/// and enables a View to bind commands to objects that are not part of the element tree.
/// </summary>
public class DelegateCommand : ICommand
{
#region Constructors /// <summary>
/// Constructor
/// </summary>
public DelegateCommand(Action executeMethod)
: this(executeMethod, null, false)
{
} /// <summary>
/// Constructor
/// </summary>
public DelegateCommand(Action executeMethod, Func<bool> canExecuteMethod)
: this(executeMethod, canExecuteMethod, false)
{
} /// <summary>
/// Constructor
/// </summary>
public DelegateCommand(Action executeMethod, Func<bool> canExecuteMethod, bool isAutomaticRequeryDisabled)
{
if (executeMethod == null)
{
throw new ArgumentNullException("executeMethod");
} _executeMethod = executeMethod;
_canExecuteMethod = canExecuteMethod;
_isAutomaticRequeryDisabled = isAutomaticRequeryDisabled;
} #endregion #region Public Methods /// <summary>
/// Method to determine if the command can be executed
/// </summary>
public bool CanExecute()
{
if (_canExecuteMethod != null)
{
return _canExecuteMethod();
}
return true;
} /// <summary>
/// Execution of the command
/// </summary>
public void Execute()
{
if (_executeMethod != null)
{
_executeMethod();
}
} /// <summary>
/// Property to enable or disable CommandManager's automatic requery on this command
/// </summary>
public bool IsAutomaticRequeryDisabled
{
get
{
return _isAutomaticRequeryDisabled;
}
set
{
if (_isAutomaticRequeryDisabled != value)
{
if (value)
{
CommandManagerHelper.RemoveHandlersFromRequerySuggested(_canExecuteChangedHandlers);
}
else
{
CommandManagerHelper.AddHandlersToRequerySuggested(_canExecuteChangedHandlers);
}
_isAutomaticRequeryDisabled = value;
}
}
} /// <summary>
/// Raises the CanExecuteChaged event
/// </summary>
public void RaiseCanExecuteChanged()
{
OnCanExecuteChanged();
} /// <summary>
/// Protected virtual method to raise CanExecuteChanged event
/// </summary>
protected virtual void OnCanExecuteChanged()
{
CommandManagerHelper.CallWeakReferenceHandlers(_canExecuteChangedHandlers);
} #endregion #region ICommand Members /// <summary>
/// ICommand.CanExecuteChanged implementation
/// </summary>
public event EventHandler CanExecuteChanged
{
add
{
if (!_isAutomaticRequeryDisabled)
{
CommandManager.RequerySuggested += value;
}
CommandManagerHelper.AddWeakReferenceHandler(ref _canExecuteChangedHandlers, value, );
}
remove
{
if (!_isAutomaticRequeryDisabled)
{
CommandManager.RequerySuggested -= value;
}
CommandManagerHelper.RemoveWeakReferenceHandler(_canExecuteChangedHandlers, value);
}
} /// <summary>
///
/// </summary>
/// <param name="parameter"></param>
/// <returns></returns>
bool ICommand.CanExecute(object parameter)
{
return CanExecute();
} /// <summary>
///
/// </summary>
/// <param name="parameter"></param>
void ICommand.Execute(object parameter)
{
Execute();
} #endregion #region Data
/// <summary>
///
/// </summary>
private readonly Action _executeMethod = null;
/// <summary>
///
/// </summary>
private readonly Func<bool> _canExecuteMethod = null;
/// <summary>
///
/// </summary>
private bool _isAutomaticRequeryDisabled = false;
/// <summary>
///
/// </summary>
private List<WeakReference> _canExecuteChangedHandlers; #endregion
} /// <summary>
/// This class allows delegating the commanding logic to methods passed as parameters,
/// and enables a View to bind commands to objects that are not part of the element tree.
/// </summary>
/// <typeparam name="TExecuteParameter">Type of the parameter passed to the delegates</typeparam>
public class DelegateCommand<TExecuteParameter> : ICommand
{
#region Constructors /// <summary>
/// Constructor
/// </summary>
public DelegateCommand(Action<TExecuteParameter> onExecute)
: this(onExecute, null, false)
{
} /// <summary>
/// Constructor
/// </summary>
public DelegateCommand(Action<TExecuteParameter> onExecute, Func<TExecuteParameter, bool> canExecute)
: this(onExecute, canExecute, false)
{
} /// <summary>
/// Constructor
/// </summary>
public DelegateCommand(Action<TExecuteParameter> onExecute, Func<TExecuteParameter, bool> canExecute, bool isAutomaticRequeryDisabled)
{
if (onExecute == null)
{
throw new ArgumentNullException("executeMethod");
}
_onExecute = onExecute;
_canExecute = canExecute;
_isAutomaticRequeryDisabled = isAutomaticRequeryDisabled;
} #endregion #region Public Methods /// <summary>
/// Method to determine if the command can be executed
/// </summary>
public bool CanExecute(TExecuteParameter parameter)
{
if (_canExecute != null)
{
return _canExecute(parameter);
}
return true;
} /// <summary>
/// Execution of the command
/// </summary>
public void Execute(TExecuteParameter parameter)
{
if (_onExecute != null)
{
_onExecute(parameter);
}
} /// <summary>
/// Raises the CanExecuteChaged event
/// </summary>
public void RaiseCanExecuteChanged()
{
OnCanExecuteChanged();
} /// <summary>
/// Protected virtual method to raise CanExecuteChanged event
/// </summary>
protected virtual void OnCanExecuteChanged()
{
CommandManagerHelper.CallWeakReferenceHandlers(_canExecuteChangedHandlers);
} /// <summary>
/// Property to enable or disable CommandManager's automatic requery on this command
/// </summary>
public bool IsAutomaticRequeryDisabled
{
get
{
return _isAutomaticRequeryDisabled;
}
set
{
if (_isAutomaticRequeryDisabled != value)
{
if (value)
{
CommandManagerHelper.RemoveHandlersFromRequerySuggested(_canExecuteChangedHandlers);
}
else
{
CommandManagerHelper.AddHandlersToRequerySuggested(_canExecuteChangedHandlers);
}
_isAutomaticRequeryDisabled = value;
}
}
} #endregion #region ICommand Members /// <summary>
/// ICommand.CanExecuteChanged implementation
/// </summary>
public event EventHandler CanExecuteChanged
{
add
{
if (!_isAutomaticRequeryDisabled)
{
CommandManager.RequerySuggested += value;
}
CommandManagerHelper.AddWeakReferenceHandler(ref _canExecuteChangedHandlers, value, );
}
remove
{
if (!_isAutomaticRequeryDisabled)
{
CommandManager.RequerySuggested -= value;
}
CommandManagerHelper.RemoveWeakReferenceHandler(_canExecuteChangedHandlers, value);
}
} /// <summary>
///
/// </summary>
/// <param name="parameter"></param>
/// <returns></returns>
bool ICommand.CanExecute(object parameter)
{
// if T is of value type and the parameter is not
// set yet, then return false if CanExecute delegate
// exists, else return true
var type = typeof(TExecuteParameter);
if (type.IsValueType && type.IsPrimitive)
{
if (int.TryParse(parameter.ToString(), out int intResult))
{
return CanExecute((TExecuteParameter)(object)intResult);
}
} if (parameter == null && type.IsValueType)
{
return (_canExecute == null);
}
return CanExecute((TExecuteParameter)parameter);
} /// <summary>
///
/// </summary>
/// <param name="parameter"></param>
void ICommand.Execute(object parameter)
{
Execute((TExecuteParameter)parameter);
} #endregion #region Data
/// <summary>
///
/// </summary>
private readonly Action<TExecuteParameter> _onExecute = null;
/// <summary>
///
/// </summary>
private readonly Func<TExecuteParameter, bool> _canExecute = null;
/// <summary>
///
/// </summary>
private bool _isAutomaticRequeryDisabled = false;
/// <summary>
///
/// </summary>
private List<WeakReference> _canExecuteChangedHandlers; #endregion
} /// <summary>
/// This class contains methods for the CommandManager that help avoid memory leaks by
/// using weak references.
/// </summary>
internal class CommandManagerHelper
{
internal static void CallWeakReferenceHandlers(List<WeakReference> handlers)
{
if (handlers != null)
{
// Take a snapshot of the handlers before we call out to them since the handlers
// could cause the array to me modified while we are reading it. EventHandler[] callees = new EventHandler[handlers.Count];
int count = ; for (int i = handlers.Count - ; i >= ; i--)
{
WeakReference reference = handlers[i];
EventHandler handler = reference.Target as EventHandler;
if (handler == null)
{
// Clean up old handlers that have been collected
handlers.RemoveAt(i);
}
else
{
callees[count] = handler;
count++;
}
} // Call the handlers that we snapshotted
for (int i = ; i < count; i++)
{
EventHandler handler = callees[i];
handler(null, EventArgs.Empty);
}
}
} /// <summary>
///
/// </summary>
/// <param name="handlers"></param>
internal static void AddHandlersToRequerySuggested(List<WeakReference> handlers)
{
if (handlers != null)
{
foreach (WeakReference handlerRef in handlers)
{
EventHandler handler = handlerRef.Target as EventHandler;
if (handler != null)
{
CommandManager.RequerySuggested += handler;
}
}
}
} /// <summary>
///
/// </summary>
/// <param name="handlers"></param>
internal static void RemoveHandlersFromRequerySuggested(List<WeakReference> handlers)
{
if (handlers != null)
{
foreach (WeakReference handlerRef in handlers)
{
EventHandler handler = handlerRef.Target as EventHandler;
if (handler != null)
{
CommandManager.RequerySuggested -= handler;
}
}
}
} /// <summary>
///
/// </summary>
/// <param name="handlers"></param>
/// <param name="handler"></param>
internal static void AddWeakReferenceHandler(ref List<WeakReference> handlers, EventHandler handler)
{
AddWeakReferenceHandler(ref handlers, handler, -);
} /// <summary>
///
/// </summary>
/// <param name="handlers"></param>
/// <param name="handler"></param>
/// <param name="defaultListSize"></param>
internal static void AddWeakReferenceHandler(ref List<WeakReference> handlers, EventHandler handler, int defaultListSize)
{
if (handlers == null)
{
handlers = (defaultListSize > ? new List<WeakReference>(defaultListSize) : new List<WeakReference>());
} handlers.Add(new WeakReference(handler));
} /// <summary>
///
/// </summary>
/// <param name="handlers"></param>
/// <param name="handler"></param>
internal static void RemoveWeakReferenceHandler(List<WeakReference> handlers, EventHandler handler)
{
if (handlers != null)
{
for (int i = handlers.Count - ; i >= ; i--)
{
WeakReference reference = handlers[i];
EventHandler existingHandler = reference.Target as EventHandler;
if ((existingHandler == null) || (existingHandler == handler))
{
// Clean up old handlers that have been collected
// in addition to the handler that is to be removed.
handlers.RemoveAt(i);
}
}
}
}
}
}
 <Button Width="60"
Height="30"
DataContext="{Binding RelativeSource={RelativeSource AncestorType=Window}}"
Command="{Binding TestCommand}"
CommandParameter="123">Test</Button>

WPF Custom Command And Binding的更多相关文章

  1. [WPF]如何调试Data Binding

    前言 在WPF开发中,将ViewModel中对象绑定到UI上时,会出现明明已经将数据对象Binding到UI,但是UI上就是不显示等等的问题.这篇博客将介绍WPF Data Binding相关的内容, ...

  2. ClassLibary和WPF User Control LIbary和WPF Custom Control Libary的异同

    说来惭愧,接触WPF这么长时间了,今天在写自定义控件时遇到一个问题:运行界面中并没有显示自定义控件,经调试发现原来没有加载Themes中的Generic.xaml. 可是为什么在其他solution中 ...

  3. Typora + PicGo-Core + Custom Command 实现上传图片到图床

    教程参考 Typora+PicGo-Core(command line)+Gitee实现图片上传到图床 主要借鉴 picgo 操作命令 Typora + PicGo + Gitee 实现图片自动上传到 ...

  4. silverlight wpf DataTemplate Command binding

    <Grid x:Name="LayoutRoot" Background="White"> <CommonControl:NoapDataGr ...

  5. wpf custom control

    最近在做WPF,记录一下自定义控件的制作过程,源码请点击:源码. 1.目标 实现一个如图所示的可增减的数字框: 2.先画Template 可以在Generic.xaml中画,也可以用MergedDic ...

  6. WPF 定义Command

    直接上代码: public class LoginDelegateCommand : ICommand { private Action _execute; private Predicate< ...

  7. Zara带你快速入门WPF(4)---Command与功能区控件

    前言:许多数据驱动的应用程序都包含菜单和工具栏或功能区控件,允许用户控制操作,在WPF中,也可以使用功能区控件,所以这里介绍菜单和功能区控件. 一.菜单控件 在WPF中,菜单很容易使用Menu和Men ...

  8. WPF 自定义Command

    无参Command: internal class DelegateCommand : ICommand { private readonly Action _execute; private rea ...

  9. Recommended Practices for WPF Custom Control Developers

    I have always found that there isn’t enough documentation about Custom Control development in WPF. M ...

随机推荐

  1. iOS 通知、本地通知和推送通知有什么区别? APNS机制。

    本地/推送通知为不同的需要而设计.本地通知对于iPhone,iPad或iPod来说是本地的.而推送通知——来自于设备外部.它们来自远程服务器——也叫做远程通知——推送给设备上的应用程序(使用APNs) ...

  2. uvm_driver——老司机带带我

    文件:src/comps/uvm_driver.svh类: uvm_driver uvm_driver继承(C++中叫继承)自uvm_component,其中定义了两个Ports:seq_item_p ...

  3. mysqldumpslow及explain使用简介

  4. 修改本地dns域名对应的 ip

    C:\Windows\System32\drivers\etc 打开 hosts 文件 在浏览器 访问 http://a.com,就相当于访问 127.0.0.2 这个ip了

  5. 洛谷 P2419 [USACO08JAN]牛大赛Cow Contest

    题目背景 [Usaco2008 Jan] 题目描述 N (1 ≤ N ≤ 100) cows, conveniently numbered 1..N, are participating in a p ...

  6. navicate连接mysql

    1. 打开navicate,选择连接 2. 编辑连接属性 编辑完成之后,连接成功.

  7. 图片,二进制,oracle数据库

    图片在oracle数据库中一般以二进制存在,存储类型是blob,然而clob类型一般存储的是大于4000的字符,不能用来存储图像这样的二进制内容,下面展示一下实现图像,二进制,oracle 数据库的应 ...

  8. 1991: C语言实验——大小写转换

    1991: C语言实验——大小写转换 Time Limit: 1 Sec  Memory Limit: 64 MBSubmit: 183  Solved: 109[Submit][Status][We ...

  9. WINDOWS-API:API函数大全

    操作系统除了协调应用程序的执行.内存分配.系统资源管理外,同时也是一个很大的服务中心,调用这个服务中心的各种服务(每一种服务是一个函数),可以帮肋应用程序达到开启视窗.描绘图形.使用周边设备的目的,由 ...

  10. Swift 中 String 与 CChar 数组的转换

    在现阶段Swift的编码中,我们还是有很多场景需要调用一些C函数.在Swift与C的混编中,经常遇到的一个问题就是需要在两者中互相转换字符串.在C语言中,字符串通常是用一个char数组来表示,在Swi ...