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. 第5章 引用类型---JS红宝书书摘系列笔记

    在ECMAScript中,引用类型是一种数据结构,用于将数据和功能组织在一起,描述的是一类对象所具有的属性和方法.而对象是某个特定引用类型的实例. 一.Object类型 可以通过Object构造函数创 ...

  2. jsp中<c:forEach varStatus="status">的属性值问题

    c:forEach varStatus属性 current当前这次迭代的(集合中的)项 index当前这次迭代从 0 开始的迭代索引 count当前这次迭代从 1 开始的迭代计数 first用来表明当 ...

  3. Oracle汇总

    1.数据库事务并发会产生那些问题?有哪些隔离级别,分别能够避免什么错误,而无法避免什么错误? a.事务并发会导致三种问题:脏读.不可重复读.幻象读 脏读:读取了未提交的数据 不可重复读:前后读取同一行 ...

  4. angulajs中引用chart.js做报表,修改线条样式

    目前还有个问题,在手机上看,当折线y轴值超过1000,会有点问题 1.下载chart js,可以用bower 命令下载 http://www.chartjs.org/docs/#line-chart- ...

  5. python super详解

    一.super() 的入门使用 - 在类的继承中,如果重定义某个方法,该方法会覆盖父类的同名方法,但有时,我们希望能同时实现父类的功能, 这时,我们就需要调用父类的方法了,可通过使用 super 来实 ...

  6. POJ 3107 Godfather (树的重心)

    题意:求树的重心,若有多个,全部打印出来. 思路: 树的重心:在删除点v后,森林中的每棵树的节点数尽量均匀,若最大的那棵树的节点数最小,称v为树的重心. 这道题只是求树的所有重心,当且经当这棵树有对称 ...

  7. POJ 1739 Tony's Tour (插头DP,轮廓线DP)

    题意:给一个n*m的矩阵,其中#是障碍格子,其他则是必走的格子,问从左下角的格子走到右下角的格子有多少种方式. 思路: 注意有可能答案是0,就是障碍格子阻挡住了去路. 插头DP有两种比较常见的表示连通 ...

  8. JavaScript面试系列:JavaScript设计模式之桥接模式和懒加载

    我写的程序员面试系列文章 Java面试系列-webapp文件夹和WebContent文件夹的区别? 程序员面试系列:Spring MVC能响应HTTP请求的原因? Java程序员面试系列-什么是Jav ...

  9. BestCoder Round#15 1002-Instruction

    http://acm.hdu.edu.cn/showproblem.php?pid=5083 官方题解——> 1002 Instruction 先考虑编码,首先找到operation对应的编码, ...

  10. golang 强制重新全部编译

    /home/用户名/.cache 删除缓存试试?? 修改的东西老失败 编译结果总不变 神奇了 go build -a    -x -v加一句-a 强制重新编译.