【问题标题】:How to disable button on validation error when using MVVM?使用 MVVM 时如何禁用验证错误按钮?
【发布时间】:2016-12-20 04:04:55
【问题描述】:

我正在学习 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");
        }
    }

现在我想我需要将它与验证联系起来?

【问题讨论】:

  • 当使用RelayCommand构造函数的第二个参数时,按钮只启用,如果函数,第二个参数指向返回true。因此,您可以指向 IsValid 函数,而不是使用“null”作为第二个参数。
  • 我看不到您的 Command 实现,但应该有一个 CanExecute 参数可供您设置,该参数将自动用于确定 Button 是否启用。如果它基于方法而不是像 Save_CanExecute 方法中的属性,则您可能需要向对象添加 PropertyChange 通知,每当属性更改可能会使对象无效时调用 SaveCommand.RaiseCanExecuteChanged() 之类的东西。

标签: c# wpf validation mvvm


【解决方案1】:

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

您正在实现 NumberValidation 类,但我没有看到任何使用它的 xaml 代码。你需要在你的 xaml 代码中使用它,像这样:

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

但是如果你使用这种方法,验证是在 View 层完成的。所以这意味着您的 ViewModel 不知道它有错误,并且您的 IsValid 没有检测到有错误。

如果您想将所有验证都放在视图中,请使用多重绑定在错误控件和您的按钮之间添加绑定。你可以在这里看到一个例子。 Disabling button on Validation error

但是,如果您希望验证发生在 ViewModel 中,则需要您的视图模型实现 IDataErrorInfo 接口。那么你的 NumberValidation 类就没有用了。

【讨论】:

    【解决方案2】:

    通常,您可以将 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>
    

    【讨论】:

    • 尝试将 IsEnabled 绑定到我的“IsValid”函数,但它似乎不起作用。将继续检查,看看我怎样才能让它工作。
    • 它必须是返回类型为布尔值的属性。此外,它不能像您的 IsValid 函数那样具有参数。因此,在您的情况下,添加一个 IsValid 属性就足够了,该属性使用相应的参数返回您的函数的值。
    • 类似的东西? UPDATEDOP
    • 请参阅 Rachael 的评论以获取答案。因此,Command 对象已经支持启用和禁用此行为。因此,添加另一个属性(即 IsEnabled)很冗长。
    猜你喜欢
    • 1970-01-01
    • 2019-05-30
    • 1970-01-01
    • 2022-08-03
    • 2013-07-03
    • 2017-11-07
    • 2020-08-29
    • 1970-01-01
    • 2011-02-02
    相关资源
    最近更新 更多