I am learning MVVM and so far so good, except when disabling a button upon validation. My validation works flawlessly not so the disabling the button part. Here's my code:
ViewModelBase:
public class ViewModelBase : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
protected void NotifyPropertyChanged(string propertyName)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
}
My validation Class:
public class NumberValidation : ValidationRule
{
public override ValidationResult Validate(object value, System.Globalization.CultureInfo cultureInfo)
{
if (String.IsNullOrEmpty(value.ToString()))
{
return new ValidationResult(false, "No debe estar vacio");
}
double result = 0;
bool canConvert = double.TryParse(value as string, out result);
return new ValidationResult(canConvert, "No es numero valido");
}
}
And my ViewModel:
public class CommercePayment : ViewModelBase
{
private ICommand _SubmitCommand;
private PayCommerce _payCommerce;
public PayCommerce PayCommerces
{
get
{
return _payCommerce;
}
set
{
_payCommerce = value;
NotifyPropertyChanged("PayCommerces");
}
}
public CommercePayment()
{
PayCommerces = new PayCommerce();
}
void PayCommerce_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
{
NotifyPropertyChanged("PayCommerces");
}
public void Submit()
{
var test = PayCommerces.AccountNumber;
var test2 = PayCommerces.PaymentAmount;
// var test2 = PayCommerces.Commerce.MerchantFullName;
}
#region Helpers
public ICommand SubmitCommand
{
get
{
if (_SubmitCommand == null)
{
_SubmitCommand = new RelayCommand(param => this.Submit(),
null);
}
return _SubmitCommand;
}
}
#endregion
}
}
My XML is binded this way:
<Controls:Tile x:Name="tlProcesar" Title=""
TiltFactor="2"
Width="Auto" Height="Auto"
Count="Procesar"
Command="{Binding SubmitCommand}" Margin="185,189,200,-59"
>
</Controls:Tile>
In my codebehind I have this (was testing and learning):
private void Save_CanExecute(object sender, CanExecuteRoutedEventArgs e)
{
e.CanExecute = IsValid(sender as DependencyObject);
}
private void Save_Executed(object sender, ExecutedRoutedEventArgs e)
{
ViewModel.CommercePayment payments = new ViewModel.CommercePayment();
payments.Submit();
}
private bool IsValid(DependencyObject obj)
{
return !Validation.GetHasError(obj) && LogicalTreeHelper.GetChildren(obj).OfType<DependencyObject>().All(IsValid);
}
If I changed my control binding to:
Command="ApplicationCommands.Save"
Then the button is disabled, but of course I get no data back in my Submit() method in the ViewModel because its not binding. If I leave it as it is, even with failing validation the button will still work. What can I do?
Update 1:
Created this:
public bool IsValid
{
get { return _isValid; }
set
{
_isValid = value;
NotifyPropertyChanged("IsValid");
}
}
Now I guess I need to tie it to the validation?