2009-06-25 26 views
2

FirstName値がnullまたは空で、ErrorTemplateの一部であるTextBlockにエラーメッセージを表示しようとすると、ApplicationExceptionがスローされます。しかし、常に "呼び出しの対象に例外がスローされました"と表示されます。ここWPF ExceptionValidationRuleがValidation.Errorsコレクションに表示されない

public string FirstName 
     { 
      get { return _firstName;} 
      set 
      { 
       if(String.IsNullOrEmpty(value)) 
        throw new ApplicationException("FirstName cannot be null or empty!"); 
       _firstName = value; 

       OnPropertyChanged("FirstName"); 
      } 
     } 

<Style x:Key="TextBoxStyle" TargetType="TextBox"> 

      <Setter Property="Validation.ErrorTemplate"> 
       <Setter.Value> 
        <ControlTemplate> 
         <DockPanel LastChildFill="True"> 
          <TextBlock DockPanel.Dock="Right" 
         Foreground="Orange" 
         FontSize="12pt" 
         Text="{Binding ElementName=MyAdorner, Path=AdornedElement.(Validation.Errors)[0].ErrorContent}"> 
          </TextBlock> 
          <Border BorderBrush="Green" BorderThickness="1"> 
           <AdornedElementPlaceholder Name="MyAdorner" /> 
          </Border> 
         </DockPanel> 
        </ControlTemplate> 
       </Setter.Value> 
      </Setter> 

     </Style> 

そして最後にTextBoxコントロールで:

<TextBox Name="txtFirstName" Style="{StaticResource TextBoxStyle}" Grid.Column="1" Grid.Row="0" Height="20" Width="100" Margin="10"> 
       <TextBox.Text> 
        <Binding Path="FirstName"> 
         <Binding.ValidationRules> 
          <ExceptionValidationRule /> 
         </Binding.ValidationRules> 
        </Binding> 
       </TextBox.Text> 

      </TextBox> 

答えて

5

私は先日、この経て、私は、プロパティをオフに例外を取り、バリデーションクラスを使用して終了。それだけで次のようになりますので、

<TextBox Name="txtFirstName" Style="{StaticResource TextBoxStyle}" Grid.Column="1" Grid.Row="0" Height="20" Width="100" Margin="10"> 
     <TextBox.Text> 
      <Binding Path="FirstName" > 
       <Binding.ValidationRules> 
        <validators:StringRangeValidationRule 
            MinimumLength="1" 
            MaximumLength="40" 
            ErrorMessage="Required" /> 
       </Binding.ValidationRules> 
      </Binding> 
     </TextBox.Text> 

...

private string _firstName; 
    public string FirstName 
    { 
     get { return _firstName; } 
     set 
     { 
      _firstName = value; 

      OnPropertyChanged("FirstName"); 
     } 
    } 

がHERESに検証クラスは(私がオフにインターネットのどこかにこれをポシェ)...あなたの財産から例外を削除します
public class StringRangeValidationRule : ValidationRule 
{ 
    private int _minimumLength = -1; 
    private int _maximumLength = -1; 
    private string _errorMessage; 

    public int MinimumLength 
    { 
     get { return _minimumLength; } 
     set { _minimumLength = value; } 
    } 

    public int MaximumLength 
    { 
     get { return _maximumLength; } 
     set { _maximumLength = value; } 
    } 

    public string ErrorMessage 
    { 
     get { return _errorMessage; } 
     set { _errorMessage = value; } 
    } 

    public override ValidationResult Validate(object value, 
     CultureInfo cultureInfo) 
    { 
     ValidationResult result = new ValidationResult(true, null); 
     string inputString = (value ?? string.Empty).ToString(); 
     if (inputString.Length < this.MinimumLength || 
       (this.MaximumLength > 0 && 
       inputString.Length > this.MaximumLength)) 
     { 
      result = new ValidationResult(false, this.ErrorMessage); 
     } 
     return result; 
    } 
} 

xamlに検証クラスが存在する場所に名前空間参照を追加する必要があります

のような何か...このことができます

xmlns:validators="clr-namespace:WpfApplication1" 

・ホープと呼ばれるバリ(私はちょうど完全性のためにあなたがこれを知っていると確信しています)!

乾杯、

アンディ

+0

ありがとうございました。もう一つ質問!検証は、TextBoxに何かを入力してからそれを削除し、TextBoxからフォーカスを失った場合にのみ発生します。TextBoxが空でフォーカスが失われたときに検証を実行するには、とにかくありますか? – azamsharp

3

繰り返しますが、私は今週まったく同じことを通じて行ってきました!私は)

<validators:ValidatedContent Name="Validator" > 

<!-- All your textboxes here --> 

</validators:ValidatedContent> 

は、あなたが他のものを入れて同じ場所に以下のクラスを追加します...そしてあなたがValidator.Validate(呼び出すことができます...これであなたのテキストボックスをラップし、ウェブ上で次を発見しましたボタンをクリックするかどこからでもあなたが望む場所から。など、あなたが保存したいかどうかを決定するために使用することができますIsContentValidプロパティは、私もそう、私はそれが誰かを助ける場合には、私の回避策を掲載しています。このいくつかの問題があった

public class ValidatedContent : Decorator 
{ 

    #region Public Constructors 

    /// <summary> 
    /// Initializes a new instance of ValidatedContent 
    /// </summary> 
    public ValidatedContent() 
    { 
     ErrorMessages = new ObservableCollection<string>(); 

     Loaded += new RoutedEventHandler(OnValidatedContentLoaded); 
    } 

    #endregion 

    #region Event Handlers 

    /// <summary> 
    /// Handles the loaded event 
    /// </summary> 
    /// <param name="sender"></param> 
    /// <param name="e"></param> 
    private void OnValidatedContentLoaded(object sender, RoutedEventArgs e) 
    { 
     Queue<DependencyObject> elementQueue = new Queue<DependencyObject>(); 
     elementQueue.Enqueue(this.Child); 

     // Iterate over all the child elements 
     while (elementQueue.Count > 0) 
     { 
      // Dequeue the first element in the queue 
      DependencyObject element = elementQueue.Dequeue(); 

      if (element != null) 
      { 
       foreach (var childElement in LogicalTreeHelper.GetChildren(element)) 
       { 
        if (childElement is DependencyObject) 
         elementQueue.Enqueue((DependencyObject)childElement); 
       } 
      } 

      Control control = element as Control; 

      // Mark the element as valid if it is a control 
      if (control != null && GetIsRequired(element)) 
      { 
       control.SetValue(Control.StyleProperty, RequiredControlStyle); 
      } 
     } 

    } 

    #endregion 

    #region Dependency Properties 

    public static readonly DependencyProperty IsContentValidProperty = 
     DependencyProperty.Register("IsContentValid", typeof(bool), 
     typeof(ValidatedContent), new UIPropertyMetadata(false)); 

    public static readonly DependencyProperty ErrorMessagesProperty = 
     DependencyProperty.Register("ErrorMessages", typeof(ObservableCollection<string>), 
     typeof(ValidatedContent), new UIPropertyMetadata(null)); 

    public static readonly DependencyProperty RequiredControlStyleProperty = 
     DependencyProperty.Register("RequiredControlStyle", typeof(Style), 
     typeof(ValidatedContent), new UIPropertyMetadata(null)); 

    public static readonly DependencyProperty IsRequiredProperty = 
     DependencyProperty.RegisterAttached("IsRequired", typeof(bool), 
     typeof(ValidatedContent), new UIPropertyMetadata(false)); 

    #endregion 

    #region Public Properties 

    /// <summary> 
    /// Gets or sets the style to mark a required control 
    /// </summary> 
    public Style RequiredControlStyle 
    { 
     get { return (Style)GetValue(RequiredControlStyleProperty); } 
     set { SetValue(RequiredControlStyleProperty, value); } 
    } 

    /// <summary> 
    /// Gets or sets the error messages for the validated content 
    /// </summary> 
    public ObservableCollection<string> ErrorMessages 
    { 
     get { return (ObservableCollection<string>)GetValue(ErrorMessagesProperty); } 
     private set { SetValue(ErrorMessagesProperty, value); } 
    } 

    /// <summary> 
    /// Gets if the content is valid 
    /// </summary> 
    public bool IsContentValid 
    { 
     get { return (bool)GetValue(IsContentValidProperty); } 
     private set { SetValue(IsContentValidProperty, value); } 
    } 

    #endregion 

    #region Public Methods 

    /// <summary> 
    /// Validates the content of the decorator 
    /// </summary> 
    public void Validate() 
    { 
     IsContentValid = true; 
     ErrorMessages.Clear(); 

     Queue<DependencyObject> elementQueue = new Queue<DependencyObject>(); 
     elementQueue.Enqueue(this.Child); 

     // Iterate over all the child elements 
     while (elementQueue.Count > 0) 
     { 
      // Dequeue the first element in the queue 
      DependencyObject element = elementQueue.Dequeue(); 


      foreach (var childElement in LogicalTreeHelper.GetChildren(element)) 
      { 
       if (childElement is DependencyObject) 
        elementQueue.Enqueue((DependencyObject)childElement); 
      } 


      // Validate the bindings of the element 
      ValidateBindings(element); 
     } 
    } 

    #endregion 

    #region Private Methods 

    /// <summary> 
    /// Validates the bindings of the dependency object 
    /// </summary> 
    /// <param name="element"></param> 
    private void ValidateBindings(DependencyObject element) 
    { 
     if (element != null) 
     { 
      Type elementType = element.GetType(); 

      FieldInfo[] dependencyPropertyFields = elementType.GetFields(
       BindingFlags.Static | BindingFlags.Public | BindingFlags.DeclaredOnly); 

      // Iterate over all dependency properties 
      foreach (FieldInfo dependencyPropertyField in dependencyPropertyFields) 
      { 
       DependencyProperty dependencyProperty = 
        dependencyPropertyField.GetValue(element) as DependencyProperty; 

       if (dependencyProperty != null) 
       { 
        Binding binding = BindingOperations.GetBinding(element, dependencyProperty); 
        BindingExpression bindingExpression = BindingOperations.GetBindingExpression(element, dependencyProperty); 

        // Issue 1822 - Extra check added to prevent null reference exceptions 
        if (binding != null && bindingExpression != null) 
        { 
         // Validate the validation rules of the binding 
         foreach (ValidationRule rule in binding.ValidationRules) 
         { 
          ValidationResult result = rule.Validate(element.GetValue(dependencyProperty), 
           CultureInfo.CurrentCulture); 

          bindingExpression.UpdateSource(); 

          if (!result.IsValid) 
          { 
           ErrorMessages.Add(result.ErrorContent.ToString()); 
          } 

          IsContentValid &= result.IsValid; 
         } 
        } 
       } 
      } 
     } 
    } 

    #endregion 

    #region Static Methods 

    /// <summary> 
    /// Gets the value for the IsRequired attached property 
    /// </summary> 
    /// <param name="obj"></param> 
    /// <returns></returns> 
    public static bool GetIsRequired(DependencyObject obj) 
    { 
     return (bool)obj.GetValue(IsRequiredProperty); 
    } 

    /// <summary> 
    /// Sets the value for the IsRequired attached property 
    /// </summary> 
    /// <param name="obj"></param> 
    /// <param name="value"></param> 
    public static void SetIsRequired(DependencyObject obj, bool value) 
    { 
     obj.SetValue(IsRequiredProperty, value); 
    } 

    #endregion 
} 
+0

ありがとう! 私は、検証を処理するためのユーザーコントロールを作成中です。 RequiredTextBoxコントロール、RegularExpressionTextBoxなど – azamsharp

0

もあります。 コードでトリガされた例外がTargetInvocationExceptionにラップされるため、テキストブロックに表示されるメッセージが正しいものではありません。したがって、表示されるエラーメッセージは、その例外の1つです。「例外は呼び出しの対象にスローされました」です。

私はその方法がなければならないかなり確信して表示したい例外はに、TargetInvocationExceptionののInnerExceptionに実際にアクセス可能であり、あなたはので、あなたのXAMLで、次の文

Text="{Binding ElementName=MyAdorner, Path=AdornedElement.(Validation.Errors)[0].ErrorContent.InnerException.Message}" 

を使用して、それにメッセージを表示することができますErrorContentフィールドに含まれているエラーは正しいものですが、私はそれを理解するのに十分ではありません。

関連する問題