如何在使用MVVM时禁用验证错误按钮

本文关键字:验证 错误 按钮 MVVM | 更新日期: 2023-09-27 18:24:11

我正在学习MVVM,到目前为止一切都很好,除了在验证时禁用按钮时。我的验证工作完美无瑕,而不是禁用按钮部分。这是我的代码:

ViewModelBase:

public class ViewModelBase : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;
    protected void NotifyPropertyChanged(string propertyName)
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}

我的验证类:

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");
    }

}

我的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
}

}

我的XML是这样绑定的:

<Controls:Tile x:Name="tlProcesar" Title="" 
                TiltFactor="2"
                Width="Auto" Height="Auto" 
                Count="Procesar"
                Command="{Binding SubmitCommand}" Margin="185,189,200,-59"
                           >
            </Controls:Tile>

在我的代码库中,我有这个(正在测试和学习):

    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);
    }

如果我将控制绑定更改为:

 Command="ApplicationCommands.Save"

然后按钮被禁用,但当然,我在ViewModel中的Submit()方法中没有得到任何数据,因为它没有绑定。如果我保持原样,即使验证失败,按钮仍然可以工作。我能做什么?

更新1:

创建此:

public bool IsValid
    {
        get { return _isValid; }
        set
        {
            _isValid = value;
            NotifyPropertyChanged("IsValid");
        }
    }

现在我想我需要把它和验证联系起来?

如何在使用MVVM时禁用验证错误按钮

我可以看到,您在设置中混合了两种验证解决方案,一半发生在视图中,另一种发生在视图模型中。

您正在实现NumberValidation类,但我没有看到任何使用它的xaml代码。您需要在xaml代码中使用它,如下所示:

<TextBox.Text>
  <Binding Path="PayCommerces">
    <Binding.ValidationRules>
      <val:NumberValidation/>
    </Binding.ValidationRules>
  </Binding>
</TextBox.Text>

但是,如果使用此方法,验证将在"视图"层中完成。因此,这意味着你的ViewModel不知道它有错误,而你的IsValid也没有检测到有错误。

如果要将所有验证都放在视图中,请使用multibinding在错误中的控件和按钮之间添加绑定。你可以在这里看到一个例子。验证错误上的禁用按钮

但是,如果您希望验证在ViewModel中进行,则需要您的视图模型来实现IDataErrorInfo接口。那么NumberValidation类将毫无用处。

通常,您可以将Button的IsEnabled属性绑定到xaml.cs中返回"IsValid"状态的属性。

<Controls:Tile x:Name="tlProcesar" Title="" 
  TiltFactor="2"
  Width="Auto" Height="Auto" 
  Count="Procesar"
  Command="{Binding SubmitCommand}" Margin="185,189,200,-59"
  IsEnabled="{Binding IsValidProperty}">
</Controls:Tile>