Как передать информацию из View в ViewModel с помощью DelegateCommand?

на мой взгляд, у меня есть кнопка.

когда пользователь нажимает эту кнопку, Я хочу, чтобы ViewModel сохранил контекст TextBlock в базе данных.

<StackPanel HorizontalAlignment="Left" VerticalAlignment="Top">
    <TextBlock Text="{Binding FirstName}"/>
    <TextBox Text="Save this text to the database."/>
    <Button Content="Save" Command="{Binding SaveCommand}"/>
</StackPanel>

однако в моей DelegateCommand в моей ViewModel метод" Save () " не передает никаких аргументов, так как я могу получить данные из представления в этот момент?

#region DelegateCommand: Save
private DelegateCommand saveCommand;

public ICommand SaveCommand
{
    get
    {
        if (saveCommand == null)
        {
            saveCommand = new DelegateCommand(Save, CanSave);
        }
        return saveCommand;
    }
}

private void Save()
{
    TextBox textBox = ......how do I get the value of the view's textbox from here?....
}

private bool CanSave()
{
    return true;
}
#endregion

5 ответов


проверить эта статья MSDN Джоша Смита. В нем он показывает вариант DelegateCommand, который он вызывает RelayCommand, а делегаты Execute и CanExecute в RelayCommand принимают один параметр типа object.

используя RelayCommand, вы можете передать информацию делегатам через CommandParameter:

<Button Command="{Binding SaveCommand}" 
        CommandParameter="{Binding SelectedItem,Element=listBox1}" />

обновление

смотрим в этой статье, похоже, что существует общая версия DelegateCommand, который принимает параметр аналогичным образом. Возможно, вы захотите попробовать изменить команду сохранения на DelegateCommand<MyObject> и измените методы Save и CanSave так, чтобы они принимали параметр MyObject.


вот элегантный способ.

дайте имя вашему textbox, затем свяжите CommandParameter в кнопке с его текстовым свойством:

<StackPanel HorizontalAlignment="Left" VerticalAlignment="Top">
    <TextBlock Text="{Binding FirstName}"/>
    <TextBox x:Name="ParameterText" Text="Save this text to the database."/>
    <Button Content="Save" Command="{Binding SaveCommand}"
            CommandParameter="{Binding Text, ElementName=ParameterText}"/>
</StackPanel>

в вашей виртуальной машине:

private DelegateCommand<string> _saveCmd = new DelegateCommand<string>(Save);

public ICommand SaveCmd{ get{ return _saveCmd } }

public void Save(string s) {...}

в представлении используйте CommandParameter как пример Мэтта.


вы спрашиваете о передаче данных с помощью команды button.

что вы на самом деле хотите, я думаю, это bind текст вашего текстового поля в государственную собственность в ViewModel:

<!-- View: TextBox's text is bound to the FirstName property in your ViewModel -->
<TextBox Text="{Binding Path=FirstName}" />
<Button Command="{Binding SaveCommand}"/>

<!-- ViewModel: Expose a property for the TextBox to bind to -->
public string FirstName{ get; set; }
...
private void Save()
{
    //textBox's text is bound to --> this.FirstName;
}

Я не могу делать комментарии, я думаю. Я отвечаю на предложение Карлоса, потому что попробовал. Хотя это отличная идея, DelegateCommand нужно будет каким-то образом изменить, потому что в противном случае вы получите эту ошибку: Инициализатор поля не может ссылаться на нестатические поля, метод или свойство 'MyViewModel.Save(string)'.