I basically used a Model
's (UserAccount) Property
from my ViewModel
(CreateAccountViewModel) to bind to my View
, and call to my Command
(CreateAccountCommand).
My Model
(UserAccount):
public class UserAccount : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
private int _id;
private string _username;
private string _password;
private DateTime _dateTime;
public int Id
{
get { return _id; }
set { _id = value; OnPropertyChanged(nameof(Id)); }
}
public string Username
{
get { return _username; }
set { _username = value; OnPropertyChanged(nameof(Username)); }
}
public string Password
{
get { return _password; }
set { _password = value; OnPropertyChanged(nameof(Password)); }
}
public DateTime DateCreated
{
get { return _dateTime; }
set { _dateTime = value; OnPropertyChanged(nameof(DateCreated)); }
}
public virtual void OnPropertyChanged(string propertyName)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
My ViewModel
(CreateAccountViewModel):
public class CreateAccountViewModel: ViewModelBase
{
private UserAccount _userAccount;
public UserAccount CurrentUserAccount
{
get { return _userAccount; }
set { _userAccount = value; OnPropertyChanged(nameof(CurrentUserAccount)); }
}
public ICommand CreateAccountCommand{ get; }
public CreateAccountViewModel()
{
CreateAccountCommand= new CreateAccountCommand(this, Test);
CurrentUserAccount = new UserAccount();
}
public void Test()
{
MessageBox.Show("Random Message");
//I'm going to put my Create functionality here
}
}
My View
(CreateAccountView):
<!--The TextBox for username-->
<TextBox Grid.Column="1"
Margin="10,0,0,0"
Text="{Binding Path=CurrentUserAccount.Username, UpdateSourceTrigger=PropertyChanged}" />
<!--The PasswordBox for password-->
<components:BindablePasswordBox Grid.Column="1"
Margin="10,0,0,0"
Password="{Binding Path=CurrentUserAccount.Password, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}"
Grid.ColumnSpan="2" />
<!--The Create user button-->
<Button Grid.Row="2"
Margin="0,20,0,0"
HorizontalAlignment="Center"
Command="{Binding CreateAccountCommand}"
Content="Create Account" />
My Command
(CreateAccountCommand):
public class CreateAccountCommand: ICommand
{
private readonly CreateAccountViewModel _viewModel;
private readonly Action RunCommand;
public CreateAccountCommand(CreateAccountViewModel viewModel , Action runCommand)
{
_viewModel = viewModel;
_viewModel.PropertyChanged += ViewModel_PropertyChanged;
RunCommand = runCommand;
}
public event EventHandler CanExecuteChanged;
public bool CanExecute(object parameter)
{
//This is supposed to check whether the Username textbox and Password passwordbox is blank (if both of them are blank, the button should be disabled, else disabled
return !string.IsNullOrEmpty(_viewModel.CurrentUserAccount.Username) && !string.IsNullOrEmpty(_viewModel.CurrentUserAccount.Password);
}
public void Execute(object parameter)
{
RunCommand();
}
private void ViewModel_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
CanExecuteChanged?.Invoke(this, new EventArgs());
}
}
My PasswordBox
is bindable because I created a custom PasswordBox
with DependencyProperty
:
public partial class BindablePasswordBox : UserControl
{
public static readonly DependencyProperty PasswordProperty =
DependencyProperty.Register("Password", typeof(string), typeof(BindablePasswordBox),
new PropertyMetadata(string.Empty));
public string Password
{
get { return (string)GetValue(PasswordProperty); }
set { SetValue(PasswordProperty, value); }
}
public BindablePasswordBox()
{
InitializeComponent();
}
//This method will notify us, whenever a password in our passwordBox changes
private void PasswordBox_PasswordChanged(object sender, RoutedEventArgs e)
{
Password = passwordBox.Password; //sets the value of the DependencyProperty (PasswordProperty)
}
}
My problem here, is that, the button in my View
does not change enable/disable even if I set my command's CanExecute
to do so. Am I missing something obvious here? I really have to ask because I've been stuck here since yesterday. (My Main goal here is to disable the Create Account
button if the Textbox
and PasswordBox
have no input. Any solutions are okay)