2009-05-28 72 views
11

在我的视图中,我有一个按钮。如何使用DelegateCommand将View中的信息传递给ViewModel?

当用户点击这个按钮时,我想让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方法不传递任何参数,所以如何从在这一点上的看法得到的数据?

#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 

回答

18

结账this MSDN article by Josh Smith。在其中,他展示了DelegateCommand的一个变体,他称之为RelayCommand,并且RelayCommand上的Execute和CanExecute委托接受一个类型为object的参数。

使用RelayCommand您可以通过CommandParameter信息传递给代表:

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

更新

this article来看,它似乎有DelegateCommand的一个通用版本,它接受一个参数类似的方式。您可能想尝试将SaveCommand更改为DelegateCommand<MyObject>,并更改Save和CanSave方法,以便它们取得MyObject参数。

+2

我实际上通过将TextBox绑定到ViewModel属性(INotifyPropertyChanged)来解决我的问题,当然,Save()命令可以访问哪个值,但是您的建议非常有趣,它将检查它们。 – 2009-05-28 11:28:01

+0

Matt的解决方案肯定赢得了访问单独的绑定值的具体(合理常见)用例:在ItemsControl中执行的命令。在这里,一个按钮,比如'ListView'中的按钮可以使用它的'DataContext'作为参数,并且按钮被点击的项目和命令一起被传递。很难计算出许多项目中的哪一个按钮被点击。 – 2015-05-13 10:19:30

+1

请注意,通用的'DelegateCommand '有一个重要的限制(在运行时没有被选中 - 编译器不会抱怨):不能使用值类型作为参数。官方建议是使用可以为空的值类型(允许),并在使用之前检查它是否包含值(https://msdn.microsoft.com/en-us/library/gg431410%28v=pandp.50%29 .aspx - 请参阅“备注”部分)。 – 2015-05-13 10:23:43

9

在你的虚拟机:

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

public ICommand SaveCmd{ get{ return _saveCmd } } 

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

在您查看,使用CommandParameter像马特的例子。

+0

不是一个完整的答案,但是这指出我正确使用CommandParameter并为DelegateCommand指定一个类型。谢谢 – vdidxho 2018-03-05 23:38:24

5

你在问关于通过按钮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; 
} 
+0

这是我通常做的事情,因为TextBox的值已经绑定到viewmodel中的一个属性。没有必要将它作为参数传递给命令。 – 2010-04-20 14:12:19

+0

如果仅将文本用于一个目的,则它更有意义(代码可读性)将其作为参数传递。例如将激活密钥传递给您的虚拟机。 – 2017-09-25 10:53:25

12

这里是优雅的方式。

提供一个名称的文本框,然后在按钮绑定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> 
1

我不能作出评论,我猜。我正在回应卡洛斯的建议,因为我试了一下。虽然这是一个好主意,但DelegateCommand需要以某种方式进行修改,否则会出现此错误: 字段初始值设定项无法引用非静态字段,方法或属性'MyViewModel.Save(string)'。

相关问题