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. Vue.js - Day5 - Webpack

    在网页中会引用哪些常见的静态资源? JS .js .jsx .coffee .ts(TypeScript 类 C# 语言) CSS .css .less .sass .scss Images .jpg ...

  2. JS基础1 — 代码要注意的一些问题

    1.在一对  <script></script>  标签中,有错的js代码,那么该错误代码后面的代码不会执行. 例子:<script> alert("He ...

  3. Hibernate:Disjunction&Conjunction构造复杂的查询条件.

    Hibernate:Disjunction&Conjunction构造复杂的查询条件 Disjunction和Conjunction是逻辑或和逻辑与,如下: 用来组合一组逻辑或[or]条件的方 ...

  4. ycsb模板介绍

    #对应的mongodb uri参数等mongodb.url=mongodb://127.0.0.1:27010/test_1 #对应的mongo数据库名称mongodb.database=test_1 ...

  5. ios push Payload

    https://developer.apple.com/library/content/documentation/NetworkingInternet/Conceptual/RemoteNotifi ...

  6. MIPS程序设计实例

    第一题:用系统功能调用实现简单输入输出 题目要求 利用系统功能调用从键盘输入,转换后在屏幕上显示,具体要求如下: 1.如果输入的是字母(A~Z,区分大小写)或数字(0~9),则将其转换成对应的英文单词 ...

  7. Centos7 安装python3.5.3

    使用root用户安装:切换到root用户 su 回车,然后输入密码,切换到root用户. 新建一个脚本,如installPython.sh #!/bin/bash yum -y install zli ...

  8. 分布式文件系统ceph介绍

    ceph哲学思想 1. 每个组件必须支持扩展 2.不存在单点故障 3.解决方案必须是基于软件的.开源的.适应能力强 4.任何可能的一切必须自我管理 存在的意义:帮助企业摆脱昂贵的专属硬件 ceph目标 ...

  9. CPP-练习

    HW: 1.局部变量能否和全局变量重名? 答:能,局部会屏蔽全局.要用全局变量,需要使用"::" ;局部变量可以与全局变量同名,在函数内引用这个变量时,会用到同名的局部变量,而不会 ...

  10. js中声明函数的三种方式

    己亥年  庚午月 癸巳日  宜入宅 忌婚嫁 函数声明方式 声明 : function first(){}: 调用:first() 函数表达式声明方式   声明: var second=function ...