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
}
}