我有下一个xaml代码。
<StackPanel Grid.Row="1" x:Name="spLogin">
<TextBlock Text="E-mail:"></TextBlock>
<TextBox Name="tbLogin" Text="{Binding User.Email, Mode=TwoWay}"></TextBox>
<TextBlock Text="Password:"></TextBlock>
<TextBox Name="tbPassword" Text="{Binding User.Password, Mode=TwoWay}"></TextBox>
<StackPanel Orientation="Horizontal" HorizontalAlignment="Center">
<Button Name="btnLogin" Content="Login">
<Interactivity:Interaction.Triggers>
<Interactivity:EventTrigger EventName="Click"
x:Name="SelectChangeEvent">
<Command:EventToCommand
Command="{Binding Login, Mode=TwoWay}" PassEventArgsToCommand="False" CommandParameter="{Binding}" />
</Interactivity:EventTrigger>
</Interactivity:Interaction.Triggers>
</Button>
<Button Name="btnClear" Content="Clear"/>
</StackPanel>
</StackPanel>
</Grid>
如何将tbLogin.Text和tbPassword.Text作为一个对象的字段传递给ViewModel用户
public class User
{
public string Login{get;set;}
public string Password(get;set;)
}
答案 0 :(得分:1)
通常我会说...你不需要,因为你的ViewModel(从你的绑定中推导出来)应该包含User
属性和Login
命令iself,这样您就可以从命令的User
方法访问Excecute
属性。
但是,我注意到您呈现的用户类的用户类没有实现INotifyPropertyChanged
。因此,绑定将无法正常工作。为了使它有效,你有两种可能性:
INotifyPropertyChanged
。 - 根据您的型号及其生成方式,这并非总是如此。INotifyPropertyChanged
。 - 如果您无法控制模型的定义(例如,由Web服务代理生成),这是执行此操作的唯一方法。但是,即使您可以控制您的模型,这个选项也值得考虑,因为您可以更好地控制传递给View的内容。因此,以下示例假定您选择第二个选项:
public class MvvmViewModel1 : ViewModelBase
{
private User _user;
#region [Login]
public const string LoginPropertyName = "Login";
public string Login {
get {
return this._user.Login;
}
set {
if (this._user.Login == value) {
return;
}
var oldValue = this._user.Login;
this._user.Login = value;
RaisePropertyChanged(LoginPropertyName);
}
}
#endregion
#region [Password]
public const string PasswordPropertyName = "Password";
public string Password {
get {
return this._user.Password;
}
set {
if (this._user.Password == value) {
return;
}
var oldValue = this._user.Password;
this._user.Password = value;
RaisePropertyChanged(PasswordPropertyName);
}
}
#endregion
#region [LoginCommand]
public RelayCommand _loginCommand;
public RelayCommand LoginCommand {
get {
return _loginCommand ?? (_loginCommand = new RelayCommand(
() => {
// perform your login action here
// access Login with: this.Login
// access Password with: this.Password
},
() => {
// can execute method - sample implementation
return (!string.IsNullOrEmpty(this.Login) && !string.IsNullOrEmpty(this.Password));
}
));
}
}
#endregion
}
显然,你必须修改你的XAML以匹配这个ViewModel:
<StackPanel Grid.Row="1" x:Name="spLogin">
<TextBlock Text="E-mail:"></TextBlock>
<TextBox Name="tbLogin" Text="{Binding Login, Mode=TwoWay}"></TextBox>
<TextBlock Text="Password:"></TextBlock>
<TextBox Name="tbPassword" Text="{Binding Password, Mode=TwoWay}"></TextBox>
<StackPanel Orientation="Horizontal" HorizontalAlignment="Center">
<Button Name="btnLogin" Content="Login">
<Interactivity:Interaction.Triggers>
<Interactivity:EventTrigger EventName="Click"
x:Name="SelectChangeEvent">
<Command:EventToCommand
Command="{Binding LoginCommand}" PassEventArgsToCommand="False" />
</Interactivity:EventTrigger>
</Interactivity:Interaction.Triggers>
</Button>
<Button Name="btnClear" Content="Clear"/>
</StackPanel>
</StackPanel>
通常,如果您在数据模板内(例如ListBox中的项目模板)和/或您的命令并且您的属性不相同,则只需要使用CommandParameter
视图模型。在这种情况下,您必须定义命令以接受参数:
#region [LoginCommand]
public RelayCommand _loginCommand;
public RelayCommand LoginCommand {
get {
return _loginCommand ?? (_loginCommand = new RelayCommand(
(p) => {
// perform your login action here
},
(p) => {
// can execute method - sample implementation
return (!string.IsNullOrEmpty(this.Login) && !string.IsNullOrEmpty(this.Password));
}
));
}
}
#endregion
现在你可以使用
了CommandParameter="{Binding}"
在XAML中,将数据模板的数据上下文传递给ViewModel。
另一方面说明:您通常不需要双向绑定 - 除非您想要将信息从View中写回ViewModel。
另外作为旁注:你不能在XAML中生成/转换类;因此,如果您的ViewModel中有一个带有电子邮件/密码属性的User类,则无法在XAML中无法创建具有Login / Password属性的新用户类,并将其传递给ViewModel。绑定是强大但不是全部......; - )
答案 1 :(得分:0)
由于您的tbLogin.Text和tbPassword.Text双向绑定到User.Email和User.Password,因此您只需将CommandParameter绑定到User即可。更大的问题是:为什么你需要CommandParameter然后你的视图模型可以直接访问User属性?