Reputation: 193302
In my View, I have a button.
When the user clicks this button, I want to have the ViewModel save the context of the TextBlock in the database.
<StackPanel HorizontalAlignment="Left" VerticalAlignment="Top">
<TextBlock Text="{Binding FirstName}"/>
<TextBox Text="Save this text to the database."/>
<Button Content="Save" Command="{Binding SaveCommand}"/>
</StackPanel>
However, in my DelegateCommand in my ViewModel, the "Save()" method doesn't pass any arguments, so how do I get data from the view at that point?
#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
Upvotes: 13
Views: 48833
Reputation: 359
textblock inside grid, binding in view:
<telerik:GridViewDataColumn Header="Anunciante">
<telerik:GridViewDataColumn.CellTemplate>
<DataTemplate>
<Grid Background="{Binding AnuncianteColor}" Margin="0,7,0,7" VerticalAlignment="Center" >
<TextBlock Text="{Binding Anunciante}"
Padding="5,10,5,10"
HorizontalAlignment="Stretch"
TextAlignment="Center"
Tag="{Binding Index}"
MouseDown="AnuncianteMouseDown" />
</Grid>
</DataTemplate>
</telerik:GridViewDataColumn.CellTemplate>
</telerik:GridViewDataColumn>
and a hidden button biding for command
<Button Visibility="Collapsed" x:Name="AnunciantedoubleClick" Command="{Binding AnuncianteClickCommand}"></Button>
code behind
private void AnuncianteMouseDown(object sender, MouseButtonEventArgs e)
{
//if (e.ClickCount == 2)
//{
this.AnunciantedoubleClick.Command.Execute(((TextBlock)sender).Tag);
//}
}
and finally code in ModelView:
public ICommand AnuncianteClickCommand { get; }
in a constructor:
this.AnuncianteClickCommand = new DelegateCommand<object>(this.AnuncianteClickDelegate);
and the delegate shows a message with the row index (custom messagebox service, sorry)
private void AnuncianteClickDelegate(object v)
{
MessageBoxService.Show(v.ToString());
}
Upvotes: 0
Reputation: 204139
Check out this MSDN article by Josh Smith. In it, he shows a variation of DelegateCommand that he calls RelayCommand, and the Execute and CanExecute delegates on RelayCommand accept a single parameter of type object.
Using RelayCommand you can pass information to the delegates via a CommandParameter:
<Button Command="{Binding SaveCommand}"
CommandParameter="{Binding SelectedItem,Element=listBox1}" />
Update
Looking at this article, it appears that there is a generic version of DelegateCommand which accepts a parameter in a similar way. You might want to try changing your SaveCommand to a DelegateCommand<MyObject>
and change your Save and CanSave methods so that they take a MyObject parameter.
Upvotes: 20
Reputation: 371
I'm not allowed to make comments yet, I guess. I'm responding to Carlos' suggestion because I tried it out. While it's a great idea, DelegateCommand would need to be modified in some way because otherwise you'll get this error: A field initializer cannot reference the non-static field, method, or property 'MyViewModel.Save(string)'.
Upvotes: 1
Reputation:
here is the elegant way.
Give a name to your textbox, then bind the CommandParameter in the button to it's Text property:
<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>
Upvotes: 13
Reputation: 5977
You're asking about passing data via the button Command.
What you actually want, I think, is to bind your Textbox's text to a public property in your 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;
}
Upvotes: 5
Reputation: 945
In your VM:
private DelegateCommand<string> _saveCmd = new DelegateCommand<string>(Save);
public ICommand SaveCmd{ get{ return _saveCmd } }
public void Save(string s) {...}
In you View, use CommandParameter like Matt's example.
Upvotes: 12