WPF中控件的Event转换成Command执行(转)
细实现。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Input;
using System.Reflection;
namespace TestAutoGenerateColumnForGridView
{
public static class CommandBindingBehavior
{
public static DependencyProperty BindingEventNameProperty = DependencyProperty.RegisterAttached
("BindingEventName", typeof(string),
typeof(CommandBindingBehavior), new PropertyMetadata(null, OnBindingEventChanged));
public static string GetBindingEventName(DependencyObject obj)
{
return (string)obj.GetValue(BindingEventNameProperty);
}
public static void SetBindingEventName(DependencyObject obj, string value)
{
obj.SetValue(BindingEventNameProperty, value);
}
public static DependencyProperty BindingCommandProperty = DependencyProperty.RegisterAttached
("BindingCommand", typeof(ICommand), typeof(CommandBindingBehavior), new PropertyMetadata(null));
public static ICommand GetBindingCommand(DependencyObject obj)
{
object com = obj.GetValue(BindingCommandProperty);
if (com == null)
return null;
return (ICommand)com;
}
public static void SetBindingCommand(DependencyObject obj, ICommand value)
{
obj.SetValue(BindingCommandProperty, value);
}
private static void OnEventRaised<T>(object sender, T arg) where T: EventArgs
{
DependencyObject dependencyObject = sender as DependencyObject;
if (dependencyObject != null)
{
ICommand command = GetBindingCommand(dependencyObject);
if (command != null)
{
if (command.CanExecute(arg))
{
command.Execute(arg);
}
}
}
}
private static void OnBindingEventChanged(DependencyObject sender, DependencyPropertyChangedEventArgs arg)
{
Type senderType = sender.GetType();
EventInfo eventInfo = senderType.GetEvent(arg.NewValue.ToString());
eventInfo.AddEventHandler(sender, GenerateDelegateForEventHandler(eventInfo));
}
private static Delegate GenerateDelegateForEventHandler(EventInfo eventInfo)
{
Delegate result = null;
MethodInfo methodInfo = eventInfo.EventHandlerType.GetMethod("Invoke");
ParameterInfo[] parameters = methodInfo.GetParameters();
if (parameters.Length == 2)
{
Type currentType = typeof(CommandBindingBehavior);
Type argType = parameters[1].ParameterType;
MethodInfo eventRaisedMethod =
currentType.GetMethod("OnEventRaised", BindingFlags.NonPublic | BindingFlags.Static).MakeGenericMethod(argType);
result = Delegate.CreateDelegate(eventInfo.EventHandlerType, eventRaisedMethod);
}
return result;
}
}
}
使用:
<ListView ItemsSource ="{Binding Persons}" ItemContainerStyle="{StaticResource ResourceKey=ListViewItemStyle}"
local:CommandBindingBehavior.BindingCommand ="{Binding Path=NewFolderCommand}"
local:CommandBindingBehavior.BindingEventName="MouseUp">
<ListView.View>
</ListView.View>
</ListView>
ModelView:
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
Lazy<RelayCommand> mNewFolderCommand;
public MainWindow()
{
InitializeComponent();
this.DataContext = this;
//new folder command
mNewFolderCommand = new Lazy<RelayCommand>(() => new RelayCommand(NewFolderCommandExecuted, NewFolderCommandCanExecute));
}
#region NewFolderCommand
/// <summary>
/// Up command
/// </summary>
public ICommand NewFolderCommand
{
get { return mNewFolderCommand.Value; }
}
/// <summary>
/// Executes the Up command
/// </summary>
private void NewFolderCommandExecuted()
{
}
private bool NewFolderCommandCanExecute()
{
return true;
}
#endregion
}
依赖于:
MvvMFoudation: http://wpf.codeplex.com/
中的RelayCommand
具体实现:
namespace TestAutoGenerateColumnForGridView
{
/// <summary>
/// A command whose sole purpose is to
/// relay its functionality to other
/// objects by invoking delegates. The
/// default return value for the CanExecute
/// method is 'true'.
/// </summary>
public class RelayCommand<T> : ICommand
{
readonly Action<T> _execute;
readonly Predicate<T> _canExecute;
public RelayCommand(Action<T> execute)
: this(execute, null)
{
}
/// <summary>
/// Creates a new command.
/// </summary>
/// <param name="execute">The execution logic.</param>
/// <param name="canExecute">The execution status logic.</param>
public RelayCommand(Action<T> execute, Predicate<T> canExecute)
{
if (execute == null)
throw new ArgumentNullException("execute");
_execute = execute;
_canExecute = canExecute;
}
#region ICommand Members
[DebuggerStepThrough]
public bool CanExecute(object parameter)
{
return _canExecute == null ? true : _canExecute((T)parameter);
}
public event EventHandler CanExecuteChanged
{
add
{
if (_canExecute != null)
CommandManager.RequerySuggested += value;
}
remove
{
if (_canExecute != null)
CommandManager.RequerySuggested -= value;
}
}
public void Execute(object parameter)
{
_execute((T)parameter);
}
#endregion // ICommand Members
}
/// <summary>
/// A command whose sole purpose is to
/// relay its functionality to other
/// objects by invoking delegates. The
/// default return value for the CanExecute
/// method is 'true'.
/// </summary>
public class RelayCommand : ICommand
{
readonly Action _execute;
readonly Func<bool> _canExecute;
/// <summary>
/// Creates a new command that can always execute.
/// </summary>
/// <param name="execute">The execution logic.</param>
public RelayCommand(Action execute)
: this(execute, null)
{
}
/// <summary>
/// Creates a new command.
/// </summary>
/// <param name="execute">The execution logic.</param>
/// <param name="canExecute">The execution status logic.</param>
public RelayCommand(Action execute, Func<bool> canExecute)
{
if (execute == null)
throw new ArgumentNullException("execute");
_execute = execute;
_canExecute = canExecute;
}
#region ICommand Members
[DebuggerStepThrough]
public bool CanExecute(object parameter)
{
return _canExecute == null ? true : _canExecute();
}
public event EventHandler CanExecuteChanged
{
add
{
if (_canExecute != null)
CommandManager.RequerySuggested += value;
}
remove
{
if (_canExecute != null)
CommandManager.RequerySuggested -= value;
}
}
public void Execute(object parameter)
{
_execute();
}
#endregion // ICommand Members
}
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· .NET周刊【3月第1期 2025-03-02】
· [AI/GPT/综述] AI Agent的设计模式综述