Ответ 1
Взгляните на Marlon Grech Приведенное поведение команд, это может быть именно то, что вы ищете
Какой хороший способ привязывать команды к событиям? В моем приложении WPF есть события, которые я хотел бы захватить и обработать с помощью ViewModel, но я не уверен, как это сделать. Такие вещи, как потеря фокуса, mouseover, mousemove и т.д. Так как я пытаюсь придерживаться шаблона MVVM, мне интересно, есть ли чистое решение XAML.
Спасибо!
Взгляните на Marlon Grech Приведенное поведение команд, это может быть именно то, что вы ищете
Чтобы обрабатывать события, вы должны иметь некоторый код, который присоединяется к событию и выполняет вашу команду в ответ. Конечная цель - иметь в XAML:
MouseMoveCommand="{Binding MyCommand}"
Чтобы достичь этого, вам нужно определить прикрепленное свойство для каждого события, которое вы хотите обработать. См. этот для примера и рамки для этого.
Используйте System.Windows.Interactivity
…xmlns:i=http://schemas.microsoft.com/expression/2010/interactivity…
<Slider
<i:Interaction.Triggers>
<i:EventTrigger EventName="ValueChanged">
<i:InvokeCommandAction
Command="{Binding MyCommand}"
CommandParameter="{Binding Text, ElementName=textBox}"/>
</i:EventTrigger>
</i:Interaction.Triggers>
</Slider>
Убедитесь, что ваш проект ссылается на сборку System.Windows.Interactivity.
Источник: Блог MSDN Выполнение команды из выбранного вами события
Я реализовал его с помощью Attached Properties и Reflection. Я не могу сказать, что это лучшая реализация, но я, возможно, улучшу ее, и это может быть хорошим началом для вас.
public class EventBinding : DependencyObject
{
public static string GetEventName(DependencyObject obj)
{
return (string)obj.GetValue(EventNameProperty);
}
public static void SetEventName(DependencyObject obj, string value)
{
obj.SetValue(EventNameProperty, value);
var eventInfo = obj.GetType().GetEvent(value);
var eventHandlerType = eventInfo.EventHandlerType;
var eventHandlerMethod = typeof(EventBinding).
GetMethod("EventHandlerMethod", BindingFlags.Static | BindingFlags.NonPublic);
var eventHandlerParameters = eventHandlerType.GetMethod("Invoke").GetParameters();
var eventArgsParameterType = eventHandlerParameters.
Where(p => typeof(EventArgs).IsAssignableFrom(p.ParameterType)).
Single().ParameterType;
eventHandlerMethod = eventHandlerMethod.MakeGenericMethod(eventArgsParameterType);
eventInfo.AddEventHandler(obj, Delegate.CreateDelegate(eventHandlerType, eventHandlerMethod));
}
private static void EventHandlerMethod<TEventArgs>(object sender, TEventArgs e)
where TEventArgs : EventArgs
{
var command = GetCommand(sender as DependencyObject);
command.Execute(new EventInfo<TEventArgs>(sender, e));
}
public static readonly DependencyProperty EventNameProperty =
DependencyProperty.RegisterAttached("EventName", typeof(string), typeof(EventHandler));
public static ICommand GetCommand(DependencyObject obj)
{
return (ICommand)obj.GetValue(CommandProperty);
}
public static void SetCommand(DependencyObject obj, ICommand value)
{
obj.SetValue(CommandProperty, value);
}
public static readonly DependencyProperty CommandProperty =
DependencyProperty.RegisterAttached("Command", typeof(ICommand), typeof(EventBinding));
}
public class EventInfo<TEventArgs>
{
public object Sender { get; set; }
public TEventArgs EventArgs { get; set; }
public EventInfo(object sender, TEventArgs e)
{
Sender = sender;
EventArgs = e;
}
}
public class EventInfo : EventInfo<EventArgs>
{
public EventInfo(object sender, EventArgs e)
: base(sender, e) { }
}
public class EventBindingCommand<TEventArgs> : RelayCommand<EventInfo<TEventArgs>>
where TEventArgs : EventArgs
{
public EventBindingCommand(EventHandler<TEventArgs> handler)
: base(info => handler(info.Sender, info.EventArgs)) { }
}
<DataGrid local:EventBinding.EventName="CellEditEnding"
local:EventBinding.Command="{Binding CellEditEndingCommand}" />
private EventBindingCommand<DataGridCellEditEndingEventArgs> _cellEditEndingCommand;
public EventBindingCommand<DataGridCellEditEndingEventArgs> CellEditEndingCommand
{
get
{
return _cellEditEndingCommand ?? (
_cellEditEndingCommand = new EventBindingCommand<DataGridCellEditEndingEventArgs>(CellEditEndingHandler));
}
}
public void CellEditEndingHandler(object sender, DataGridCellEditEndingEventArgs e)
{
MessageBox.Show("Test");
}
Я не думаю, что вы можете использовать его в чистом XAML, но посмотрите на Delegate Command.
Выполнение команды, перемещение кадра и делегирование команды - довольно хороший шаблон. Он также может использоваться в Expression Blend.
На стороне "лучших практик" вы должны подумать дважды, прежде чем преобразовать событие в команду. Обычно команда - это то, что пользователь делает намеренно, событие чаще всего является лишь следствием взаимодействия и не должно покидать границы представления.