根据WPF中的验证启用禁用按钮

时间:2014-06-11 23:34:26

标签: c# wpf validation

我有一个WPF表单,它有一个文本框和一个按钮。我正在验证文本框只有字符。验证工作正常,但如果存在验证错误,我需要禁用该按钮,如果没有验证错误则启用它们。 以下是我的代码:

<TextBox Name="tbProductName" Grid.Column="1" HorizontalAlignment="Left" Height="25" Margin="4,9,0,0" Grid.Row="1" TextWrapping="Wrap" VerticalAlignment="Top" Width="213" 
                    Text="{Binding Path = ProductCode, UpdateSourceTrigger=PropertyChanged, ValidatesOnDataErrors=True,NotifyOnValidationError=True}">               
            <Validation.ErrorTemplate>
                <ControlTemplate>
                    <StackPanel>
                        <AdornedElementPlaceholder x:Name="textBox"/>
                        <TextBlock Text="{Binding [0].ErrorContent}" Foreground="Red"/>
                    </StackPanel>
                </ControlTemplate>
            </Validation.ErrorTemplate>
        </TextBox>
        <Button Name ="btnDownload" Content="Download" Grid.Column="2" HorizontalAlignment="Left" Margin="10,10,0,0" Grid.Row="1" VerticalAlignment="Top" Width="87" Height="24" Click="btnDownload_Click"/>


public class ViewModel: System.ComponentModel.INotifyDataErrorInfo 
   {
       private readonly Dictionary<string, ICollection<string>> _validationErrors = new Dictionary<string, ICollection<string>>();
       private readonly Model _productCode = new Model();
       public string ProductCode
       {
           get { return _productCode.ProductCode; }
           set
           {
               _productCode.ProductCode = value;
               ValidateModelProperty(value, "ProductCode");
           }
       }

       protected void ValidateModelProperty(object value, string propertyName)
       {
           if (_validationErrors.ContainsKey(propertyName))
               _validationErrors.Remove(propertyName);

           PropertyInfo propertyInfo = _productCode.GetType().GetProperty(propertyName);
           IList<string> validationErrors =
                 (from validationAttribute in propertyInfo.GetCustomAttributes(true).OfType<ValidationAttribute>()
                  where !validationAttribute.IsValid(value)
                  select validationAttribute.FormatErrorMessage(string.Empty))
                  .ToList();

           _validationErrors.Add(propertyName, validationErrors);
           RaiseErrorsChanged(propertyName);
       }
         /* Raise the ErrorsChanged for all properties explicitly */

       protected void ValidateModel()
       {
           _validationErrors.Clear();
           ICollection<ValidationResult> validationResults = new List<ValidationResult>();
           ValidationContext validationContext = new ValidationContext(_productCode, null, null);
           if (!Validator.TryValidateObject(_productCode, validationContext, validationResults, true))
           {
               foreach (ValidationResult validationResult in validationResults)
               {
                   string property = validationResult.MemberNames.ElementAt(0);
                   if (_validationErrors.ContainsKey(property))
                   {
                       _validationErrors[property].Add(validationResult.ErrorMessage);
                   }
                   else
                   {
                       _validationErrors.Add(property, new List<string> { validationResult.ErrorMessage });
                   }
               }
           }

           /* Raise the ErrorsChanged for all properties explicitly */
           RaiseErrorsChanged("ProductCode");
       }

       #region INotifyDataErrorInfo members
       public event EventHandler<System.ComponentModel.DataErrorsChangedEventArgs> ErrorsChanged;
       private void RaiseErrorsChanged(string propertyName)
       {
           if (ErrorsChanged != null)
               ErrorsChanged(this, new System.ComponentModel.DataErrorsChangedEventArgs(propertyName));
       }

       public System.Collections.IEnumerable GetErrors(string propertyName)
       {
           if (string.IsNullOrEmpty(propertyName)
               || !_validationErrors.ContainsKey(propertyName))
               return null;

           return _validationErrors[propertyName];
       }

       public bool HasErrors
       {
           get { return _validationErrors.Count > 0; }
       }
       #endregion

    }  

public class Model
    {
        [Required(ErrorMessage = "You must enter a product code to download.")]
        [RegularExpression(@"^[a-zA-Z]+$", ErrorMessage = "The Product Code must only contain letters (a-z, A-Z).")]
        public string ProductCode { get; set; }
    }

如何将按钮的isEnabled属性设置为Validation.HasErrors?

2 个答案:

答案 0 :(得分:2)

理想情况下,您的按钮会将其“Command”属性绑定到公共ICommand viewmodel属性。

将评估CanExecute方法,返回true或false。该按钮将相应地启用/禁用。

您可以阅读有关ICommand的更多信息,以及接口here的实现。

以下是所需的更改,假设您使用上述文章中描述的RelayCommand (See Fig. 3)实现。

注册命令

private readonly ICommand _downloadCommand = new RelayCommand(OnDownload, CanDownload);

用于绑定:

public ICommand DownloadCommand { get { return _downloadCommand; } }

执行命令时调用的方法:

private void OnDownload(object parameter) { ... Do your download code here ... }
private bool CanDownload(object parameter) { return HasErrors == false; }

更新您的XAML绑定:

<Button Content="Download" Grid.Column="2" HorizontalAlignment="Left" Margin="10,10,0,0" Grid.Row="1" VerticalAlignment="Top" Width="87" Height="24" Command="{Binding DownloadCommand}" />

答案 1 :(得分:0)

我想对你用于其余代码的Binding使用相同的技术!!

xaml

<Button Name ="btnDownload"  IsEnabled="{Binding Path= BtnIsEnabled} click="btnDownload_Click"/>

在您的代码中

    public bool BtnIsEnabled
    {
        get { return this._BtnIsEnabled; }
        set
        {
            this._BtnIsEnabled = value;
            base.OnPropertyChanged("BtnIsEnabled");
        }
    }
    private bool _BtnIsEnabled;

然后您想要禁用Button的地方

BtnIsEnabled = Validation.HasErrors ? false : true ;

显然这是一个假涂鸦。除非你追求一些非常具体的东西,否则我似乎无法找到答案。似乎你已经在你的代码中使用了绑定,我猜你知道如何。