Подтвердить что ты не робот

Связывание команд с событиями?

Какой хороший способ привязывать команды к событиям? В моем приложении WPF есть события, которые я хотел бы захватить и обработать с помощью ViewModel, но я не уверен, как это сделать. Такие вещи, как потеря фокуса, mouseover, mousemove и т.д. Так как я пытаюсь придерживаться шаблона MVVM, мне интересно, есть ли чистое решение XAML.

Спасибо!

4b9b3361

Ответ 2

Чтобы обрабатывать события, вы должны иметь некоторый код, который присоединяется к событию и выполняет вашу команду в ответ. Конечная цель - иметь в XAML:

  MouseMoveCommand="{Binding MyCommand}"

Чтобы достичь этого, вам нужно определить прикрепленное свойство для каждого события, которое вы хотите обработать. См. этот для примера и рамки для этого.

Ответ 3

Используйте 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 Выполнение команды из выбранного вами события

Ответ 4

Я реализовал его с помощью 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}" />

Model

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");
}

Ответ 5

Я не думаю, что вы можете использовать его в чистом XAML, но посмотрите на Delegate Command.

Ответ 6

Выполнение команды, перемещение кадра и делегирование команды - довольно хороший шаблон. Он также может использоваться в Expression Blend.

На стороне "лучших практик" вы должны подумать дважды, прежде чем преобразовать событие в команду. Обычно команда - это то, что пользователь делает намеренно, событие чаще всего является лишь следствием взаимодействия и не должно покидать границы представления.