Как передать информацию из View в ViewModel с DelegateCommand? - PullRequest
11 голосов
/ 28 мая 2009

В моем представлении у меня есть кнопка.

Когда пользователь нажимает эту кнопку, я хочу, чтобы 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 ]

19 голосов
/ 28 мая 2009

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

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

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

Обновление

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

12 голосов
/ 03 сентября 2009

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

Дайте имя своему текстовому полю, затем привяжите CommandParameter в кнопке к его свойству Text:

<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>
10 голосов
/ 28 мая 2009

В вашей ВМ:

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

public ICommand SaveCmd{ get{ return _saveCmd } }

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

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

5 голосов
/ 28 мая 2009

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

Я думаю, что вы действительно хотите связать текст вашего текстового поля с открытым свойством в вашей модели представления:

<!-- 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;
}
1 голос
/ 14 сентября 2010

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

...