Обычно я бы просто сказал ... вам не нужно, поскольку ваша ViewModel (выведенная из ваших привязок) должна содержать как свойство User
, так и команду Login
iself, так что вы просто может получить доступ к свойству User
из метода Excecute
вашей команды.
Однако я заметил, что пользовательский класс, представленный в представленном вами пользовательском классе, не реализует INotifyPropertyChanged
. Поэтому привязка не будет работать правильно. Чтобы это работало, у вас есть две возможности:
- Реализуйте
INotifyPropertyChanged
в своем пользовательском классе. - В зависимости от вашей модели и того, как она генерируется, это не всегда возможно.
- Дублируйте свойства вашей ViewModel и реализуйте
INotifyPropertyChanged
там. - Если у вас нет контроля над определением вашей модели (например, как оно генерируется прокси-сервером веб-службы), это единственный способ сделать это. Но даже если у вас есть контроль над вашей моделью, этот вариант стоит рассмотреть, поскольку он дает вам больший контроль над тем, что передается вашему представлению.
Итак, в следующем примере предполагается, что вы выберете второй вариант:
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, чтобы он соответствовал этой модели представления:
<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>
Обычно вам нужно использовать CommandParameter
, только если вы находитесь внутри шаблона данных (например, шаблон элемента внутри ListBox) и / или ваша команда и ваши свойства не находятся в одном и том же ViewModel. В этом случае вы должны определить свою команду для принятия параметра:
#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; так что если у вас есть класс User со свойствами Email / Password в вашей ViewModel, то невозможно создать новый класс пользователя со свойствами Login / Password из XAML и передать его в вашу ViewModel. Привязка сильна, но не всемогуща ...; -)