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

原文地址:https://www.cnblogs.com/aoldman/p/2781053.html