Передача параметра с помощью RelayCommand, определенного в ViewModel (из примера Джоша Смита)
Я хотел бы передать параметр, определенный в XAML (View) моего приложения, в класс ViewModel с помощью RelayCommand. Я последовал за Джошем Смитом превосходную статью о MVVM и реализовал следующее.
Код XAML
<Button
Command="{Binding Path=ACommandWithAParameter}"
CommandParameter="Orange"
HorizontalAlignment="Left"
Style="{DynamicResource SimpleButton}"
VerticalAlignment="Top"
Content="Button"/>
Код ViewModel
public RelayCommand _aCommandWithAParameter;
/// <summary>
/// Returns a command with a parameter
/// </summary>
public RelayCommand ACommandWithAParameter
{
get
{
if (_aCommandWithAParameter == null)
{
_aCommandWithAParameter = new RelayCommand(
param => this.CommandWithAParameter("Apple")
);
}
return _aCommandWithAParameter;
}
}
public void CommandWithAParameter(String aParameter)
{
String theParameter = aParameter;
}
#endregion
Я установил точку останова в методе CommandWithAParameter и заметил, что для параметра "Параметр" установлено значение "Яблоко", а не "Оранжевый" . Это кажется очевидным, поскольку метод CommandWithAParameter вызывается с буквальной строкой "Apple".
Однако, глядя на стек выполнения, я вижу, что "Оранжевый" , параметр CommandParameter, установленный в XAML, является значением параметра для реализации RelayCommand метода интерфейса ICommand Execute.
Это значение параметра в методе ниже стека выполнения - "Оранжевый" ,
public void Execute(object parameter)
{
_execute(parameter);
}
То, что я пытаюсь понять, - это создать свойство RelommCommand ACommandWithAParameter, чтобы он мог вызвать метод CommandWithAParameter с параметром CommandParameter "Orange", определенным в XAML.
Есть ли способ сделать это?
Почему я хочу это сделать? Часть "Локализация на лету"
В моей конкретной реализации я хочу создать SetLanguage RelayCommand, который может быть привязан к нескольким кнопкам. Я хотел бы передать два символьных идентификатора языка ( "en", "es", "ja" и т.д.) В качестве параметра CommandParameter и определить их для каждой кнопки "set language", определенной в XAML. Я хочу избежать создания команды SetLanguageToXXX для каждого языка, поддерживающего и жесткого кодирования двух идентификаторов языка символов в каждом RelayCommand в ViewModel.
Ответы
Ответ 1
Я не понимаю, почему у вас есть лишняя сложность определения лямбды в первую очередь. Почему бы просто не сделать это:
if (_aCommandWithAParameter == null)
{
_aCommandWithAParameter = new RelayCommand<object>(CommandWithAParameter);
}
private void CommandWithAParameter(object state)
{
var str = state as string;
}
Ответ 2
Вы передадите парам в лямбда команде так:
if (_aCommandWithAParameter == null)
{
_aCommandWithAParameter = new RelayCommand(
param => this.CommandWithAParameter(param)
);
}
Ответ 3
Ничего не отправил здесь, прежде чем работал у меня.
Оказывается, все ответы отсутствуют <object>
после RelayCommand
!
Это работает для меня:
public RelayCommand<object> OKCommand
{
get
{
if (_okCommand == null)
_okCommand = new RelayCommand<object>(OkCommand_Execute);
return _okCommand;
}
}
private RelayCommand<object> _okCommand = null;
private void OkCommand_Execute(object obj)
{
Result = true;
}
Если вы хотите использовать метод CanExecute
, используйте следующий код:
_okCommand = new RelayCommand<object>(OkCommand_Execute, OkCommand_CanExecute);
private bool OkCommand_CanExecute(object obj) { }
Ответ 4
Я просто пытаюсь продать свою точку зрения, проверьте это, работает ли это...
http://mywpf-visu.blogspot.com/2009/12/relay-command-how-to-pass-parameter.html
Ответ 5
Вот простое решение для командного параметра, поскольку я искал помощь по этому вопросу. Я не мог найти что-либо в Интернете, что было достаточно просто. Следующее решение работает хорошо, когда вы используете команду relaycommand.
У меня было несколько гиперссылок, для которых мне нужно было получить значение url, которое было нажато с помощью параметра команды.
Шаг 1: В вашей команде ретрансляции создайте простое свойство, которое будет содержать значение объекта параметра. Вы можете назвать это параметрированием или любым именем, которое вы предпочитаете.
public object ParameterValue
{
get;
set;
}
Шаг 2. В методе Execute класса RelayCommand задайте значение или свойство, созданное выше, параметру из метода Execute.
readonly Action<object> m_execute; // Action to execute
public void Execute(object parameter)
{
this.ParameterValue = parameter;
m_execute(parameter);
}
Шаг 3: Теперь, когда вы можете привязать CommandParameter в xaml к любому значению, которое вы хотите получить при выполнении команды.
Пример:
<TextBlock>
<Hyperlink Command="{Binding Path=NavigateUrlCmd}"
CommandParameter="{Binding ElementName=tbwebsite, Path=Text}">
<TextBlock Name="tbwebsite" Text="{Binding Path=website}"/>
</Hyperlink>
</TextBlock>
Если у вас есть команда chickenCommand, при ее выполнении вы можете получить доступ к параметру:
chickenCommand.ParameterValue
Надеюсь, это поможет кому-то. Спасибо за вашу предыдущую помощь.
Ответ 6
Я не могу заменить ссылку на имя метода для выражения lamda с ошибкой компиляции. По-видимому, и отнюдь не удивительно, что вместо лямбда нельзя использовать ссылку на нестатический метод. Я почти не вижу в нем "дополнительной сложности". Последовательное прохождение ламды имеет смысл для меня.