WPF MVVM 文本框绑定
WPF MVVM textbox binding
更新
我可以使用这个自定义实现 here。使用 prism 时存在弱引用问题。
我是 MVVM 和 Microsoft 的 Prism 的新手。我正在尝试让我的文本框绑定正常工作。如果文本框不为空,登录按钮应该可用。 setter 正在工作,但 CanOnLogin() 总是 returns false。
型号
class UserModel
{
private string userName;
private string passWord;
public string UserName
{
get { return userName; }
set { userName = value; }
}
public string PassWord
{
get { return passWord; }
set { passWord = value; }
}
}
ViewModel
class LoginViewModel : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
private UserModel user;
private DelegateCommand _loginCommand;
public UserModel User
{
get { return user; }
set { user = value; }
}
public string UserName
{
get { return user.UserName; }
set
{
user.UserName = value;
OnPropertyChanged("UserName");
}
}
public ICommand LoginCommand
{
get { return _loginCommand; }
}
public LoginViewModel()
{
_loginCommand = new DelegateCommand(OnLogin, CanOnLogin);
//implement CanOnLoginChanged here?
user = new UserModel();
}
private bool CanOnLogin()
{
if (String.IsNullOrEmpty(user.UserName))
{
return false;
}
else
{
return true;
}
}
private void OnLogin()
{
// Do something here
MessageBox.Show(user.UserName);
}
private void OnPropertyChanged(string propName)
{
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(propName));
}
public event EventHandler CanOnLoginChanged
{
add
{
CommandManager.RequerySuggested += value;
}
remove
{
CommandManager.RequerySuggested -= value;
}
}
}
查看
<TextBox Name="username" Text="{Binding Path=UserName, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}" HorizontalAlignment="Center" Margin="10" Width="175" Grid.Row="1" Grid.Column="0" Controls:TextBoxHelper.Watermark="Username" Controls:TextBoxHelper.ClearTextButton="True"/>
<Button HorizontalAlignment="Center" Margin="10" Width="87.5" Grid.Row="3" Grid.Column="0" Command="{Binding LoginCommand}">Login</Button>
代码隐藏
public partial class LoginView : MetroWindow
{
public LoginView()
{
InitializeComponent();
DataContext = new LoginViewModel();
}
}
问题是您必须创建 canExecuteChanged:
现在可以使用了。
public event EventHandler CanExecuteChanged {
add {
CommandManager.RequerySuggested += value;
}
remove {
CommandManager.RequerySuggested -= value;
}
}
can execute 将检查是否有任何相关事件可以更改状态,如果找到,会将状态从 false 更改为 true。
我相信您没有将对象参数作为参数传递给 OnLogin 和 CanOnLogin,这就是为什么它对我不起作用它确实如此并且在任何 属性 或方法而不是我所做的地方实现 canOnLogInChanged ,或者只是获取此代码并重试:
using System;
using System.Windows.Input;
class LoginViewModel : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
private UserModel user;
private DelegateCommand _loginCommand;
public UserModel User
{
get { return user; }
set { user = value; }
}
public string UserName
{
get { return user.UserName; }
set
{
user.UserName = value;
OnPropertyChanged("UserName");
}
}
public ICommand LoginCommand
{
get { return _loginCommand; }
}
public LoginViewModel()
{
_loginCommand = new DelegateCommand(OnLogin, CanOnLogin);
//implement CanOnLoginChanged here?
user = new UserModel();
}
private bool CanOnLogin(object parameter)
{
if (String.IsNullOrEmpty(user.UserName))
{
return false;
}
else
{
return true;
}
}
public event EventHandler CanOnLoginChanged
{
add
{
CommandManager.RequerySuggested += value;
}
remove
{
CommandManager.RequerySuggested -= value;
}
}
private void OnLogin(object parameter)
{
// Do something here
MessageBox.Show(user.UserName);
}
private void OnPropertyChanged(string propName)
{
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(propName));
}
}
在 CanOnLogin 中,您应该检查来自 ViewModel 的 属性,属性Changed 可以工作:
String.IsNullOrEmpty(UserName)
如果这没有帮助,请尝试将您的命令设置为延迟加载,以确保首先正确初始化所有数据。像
public ICommand LoginCommand
{
get { return _loginCommand ?? (_loginCommand = new DelegateCommand(OnLogin, CanOnLogin)); }
}
或更改 LoginViewModel() 中的初始化顺序:
user = new UserModel();
_loginCommand = new DelegateCommand(OnLogin, CanOnLogin);
你是对的:Prism 委托命令并不总是像我期望的那样工作。报道here。
检查此 Example 自定义实现。
希望对您有所帮助!
更新
我可以使用这个自定义实现 here。使用 prism 时存在弱引用问题。
我是 MVVM 和 Microsoft 的 Prism 的新手。我正在尝试让我的文本框绑定正常工作。如果文本框不为空,登录按钮应该可用。 setter 正在工作,但 CanOnLogin() 总是 returns false。
型号
class UserModel
{
private string userName;
private string passWord;
public string UserName
{
get { return userName; }
set { userName = value; }
}
public string PassWord
{
get { return passWord; }
set { passWord = value; }
}
}
ViewModel
class LoginViewModel : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
private UserModel user;
private DelegateCommand _loginCommand;
public UserModel User
{
get { return user; }
set { user = value; }
}
public string UserName
{
get { return user.UserName; }
set
{
user.UserName = value;
OnPropertyChanged("UserName");
}
}
public ICommand LoginCommand
{
get { return _loginCommand; }
}
public LoginViewModel()
{
_loginCommand = new DelegateCommand(OnLogin, CanOnLogin);
//implement CanOnLoginChanged here?
user = new UserModel();
}
private bool CanOnLogin()
{
if (String.IsNullOrEmpty(user.UserName))
{
return false;
}
else
{
return true;
}
}
private void OnLogin()
{
// Do something here
MessageBox.Show(user.UserName);
}
private void OnPropertyChanged(string propName)
{
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(propName));
}
public event EventHandler CanOnLoginChanged
{
add
{
CommandManager.RequerySuggested += value;
}
remove
{
CommandManager.RequerySuggested -= value;
}
}
}
查看
<TextBox Name="username" Text="{Binding Path=UserName, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}" HorizontalAlignment="Center" Margin="10" Width="175" Grid.Row="1" Grid.Column="0" Controls:TextBoxHelper.Watermark="Username" Controls:TextBoxHelper.ClearTextButton="True"/>
<Button HorizontalAlignment="Center" Margin="10" Width="87.5" Grid.Row="3" Grid.Column="0" Command="{Binding LoginCommand}">Login</Button>
代码隐藏
public partial class LoginView : MetroWindow
{
public LoginView()
{
InitializeComponent();
DataContext = new LoginViewModel();
}
}
问题是您必须创建 canExecuteChanged: 现在可以使用了。
public event EventHandler CanExecuteChanged {
add {
CommandManager.RequerySuggested += value;
}
remove {
CommandManager.RequerySuggested -= value;
}
}
can execute 将检查是否有任何相关事件可以更改状态,如果找到,会将状态从 false 更改为 true。
我相信您没有将对象参数作为参数传递给 OnLogin 和 CanOnLogin,这就是为什么它对我不起作用它确实如此并且在任何 属性 或方法而不是我所做的地方实现 canOnLogInChanged ,或者只是获取此代码并重试:
using System;
using System.Windows.Input;
class LoginViewModel : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
private UserModel user;
private DelegateCommand _loginCommand;
public UserModel User
{
get { return user; }
set { user = value; }
}
public string UserName
{
get { return user.UserName; }
set
{
user.UserName = value;
OnPropertyChanged("UserName");
}
}
public ICommand LoginCommand
{
get { return _loginCommand; }
}
public LoginViewModel()
{
_loginCommand = new DelegateCommand(OnLogin, CanOnLogin);
//implement CanOnLoginChanged here?
user = new UserModel();
}
private bool CanOnLogin(object parameter)
{
if (String.IsNullOrEmpty(user.UserName))
{
return false;
}
else
{
return true;
}
}
public event EventHandler CanOnLoginChanged
{
add
{
CommandManager.RequerySuggested += value;
}
remove
{
CommandManager.RequerySuggested -= value;
}
}
private void OnLogin(object parameter)
{
// Do something here
MessageBox.Show(user.UserName);
}
private void OnPropertyChanged(string propName)
{
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(propName));
}
}
在 CanOnLogin 中,您应该检查来自 ViewModel 的 属性,属性Changed 可以工作:
String.IsNullOrEmpty(UserName)
如果这没有帮助,请尝试将您的命令设置为延迟加载,以确保首先正确初始化所有数据。像
public ICommand LoginCommand
{
get { return _loginCommand ?? (_loginCommand = new DelegateCommand(OnLogin, CanOnLogin)); }
}
或更改 LoginViewModel() 中的初始化顺序:
user = new UserModel();
_loginCommand = new DelegateCommand(OnLogin, CanOnLogin);
你是对的:Prism 委托命令并不总是像我期望的那样工作。报道here。
检查此 Example 自定义实现。
希望对您有所帮助!