Я знаю, что это довольно старый вопрос, но я столкнулся с той же проблемой сегодня и не слишком интересовался ссылками на весь MVVMLight, просто чтобы использовать триггеры событий с аргументами событий.Я использовал MVVMLight в прошлом, и это отличный фреймворк, но я просто не хочу больше использовать его для своих проектов.
Что я сделал, чтобы решить эту проблему, так это создать ULTRA минимальное, ЧРЕЗВЫЧАЙНОЕ настраиваемое настраиваемое действие триггера, которое позволило бы мне привязаться к команде и предоставить конвертер аргументов событий для передачи аргументов в функции CanExecute и Execute команды.Вы не хотите передавать аргументы события дословно, так как это приведет к тому, что типы слоя представления будут отправлены на слой модели представления (что никогда не должно происходить в MVVM).
Вот EventCommandExecuter класс, который я придумал:
public class EventCommandExecuter : TriggerAction<DependencyObject>
{
#region Constructors
public EventCommandExecuter()
: this(CultureInfo.CurrentCulture)
{
}
public EventCommandExecuter(CultureInfo culture)
{
Culture = culture;
}
#endregion
#region Properties
#region Command
public ICommand Command
{
get { return (ICommand)GetValue(CommandProperty); }
set { SetValue(CommandProperty, value); }
}
public static readonly DependencyProperty CommandProperty =
DependencyProperty.Register("Command", typeof(ICommand), typeof(EventCommandExecuter), new PropertyMetadata(null));
#endregion
#region EventArgsConverterParameter
public object EventArgsConverterParameter
{
get { return (object)GetValue(EventArgsConverterParameterProperty); }
set { SetValue(EventArgsConverterParameterProperty, value); }
}
public static readonly DependencyProperty EventArgsConverterParameterProperty =
DependencyProperty.Register("EventArgsConverterParameter", typeof(object), typeof(EventCommandExecuter), new PropertyMetadata(null));
#endregion
public IValueConverter EventArgsConverter { get; set; }
public CultureInfo Culture { get; set; }
#endregion
protected override void Invoke(object parameter)
{
var cmd = Command;
if (cmd != null)
{
var param = parameter;
if (EventArgsConverter != null)
{
param = EventArgsConverter.Convert(parameter, typeof(object), EventArgsConverterParameter, CultureInfo.InvariantCulture);
}
if (cmd.CanExecute(param))
{
cmd.Execute(param);
}
}
}
}
Этот класс имеет два свойства зависимостей, одно из которых позволяет связывать команду вашей модели представления, другое позволяет связывать источник события, если оно вам необходимо во времяпреобразование аргументов события.При необходимости вы также можете указать параметры культуры (они по умолчанию соответствуют текущей культуре пользовательского интерфейса).
Этот класс позволяет адаптировать аргументы событий, чтобы они могли использоваться логикой команд модели представления.Однако, если вы хотите просто передать аргументы события дословно, просто не указывайте конвертер аргументов события.
Самое простое использование этого действия триггера в XAML:
<i:Interaction.Triggers>
<i:EventTrigger EventName="NameChanged">
<cmd:EventCommandExecuter Command="{Binding Path=Update, Mode=OneTime}" EventArgsConverter="{x:Static c:NameChangedArgsToStringConverter.Default}"/>
</i:EventTrigger>
</i:Interaction.Triggers>
Если вам нужен доступ к источнику события, вы привязываетесь к владельцу события
<i:Interaction.Triggers>
<i:EventTrigger EventName="NameChanged">
<cmd:EventCommandExecuter
Command="{Binding Path=Update, Mode=OneTime}"
EventArgsConverter="{x:Static c:NameChangedArgsToStringConverter.Default}"
EventArgsConverterParameter="{Binding ElementName=SomeEventSource, Mode=OneTime}"/>
</i:EventTrigger>
</i:Interaction.Triggers>
(это предполагает, что узлу XAML, к которому вы подключаете триггеры, назначен x:Name="SomeEventSource"
Этот XAML основан на импорте некоторых необходимых пространств имен
xmlns:cmd="clr-namespace:MyProject.WPF.Commands"
xmlns:c="clr-namespace:MyProject.WPF.Converters"
xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"
и создании IValueConverter
(в данном случае называемом NameChangedArgsToStringConverter
) для обработки фактической логики преобразования. Для базовых преобразователей Iобычно создают экземпляр конвертера static readonly
по умолчанию, который я затем могу ссылаться непосредственно в XAML, как я это делал выше.
Преимущество этого решения заключается в том, что вам действительно нужно добавить только один класс в любой проект, чтобыиспользовать структуру взаимодействия почти так же, как вы бы использовали ее с InvokeCommandAction
. Добавление одного класса (около 75 строк) должно быть намного предпочтительнее всегобиблиотека для достижения идентичных результатов.
NOTE
это несколько похоже на ответ от @adabyron, но вместо поведения использует триггеры событий.Это решение также предоставляет возможность преобразования аргументов событий, но решение @ adabyron не могло этого сделать.У меня действительно нет веской причины, почему я предпочитаю триггеры поведению, просто личный выбор.ИМО любая стратегия - это разумный выбор.