2012-03-21 4 views
11

WPF의 유효성 검사와 관련하여 여전히 어려움을 겪고 있습니다.첫 번째로드시 유효성 검사 바인딩

텍스트 입력란에 텍스트를 표시해야하는 맞춤법 검사 규칙이 있습니다. 즉, 필수 입력란 제약 조건을 적용합니다.

<TextBox local:Masking.Mask="^[a-zA-Z0-9]*$" x:Name="CameraIdCodeTextBox" Grid.Row="1" Grid.Column="1"> 
    <Binding Path="CameraIdCode" Mode="TwoWay" UpdateSourceTrigger="PropertyChanged" NotifyOnValidationError="True" ValidatesOnExceptions="True"> 
    <Binding.ValidationRules> 
     <localValidation:RequiredFieldRule /> 
    </Binding.ValidationRules> 
    </Binding> 
</TextBox> 

문제는 윈도우가 처음로드 될 때 예상대로 TextBox에 텍스트가없는 것입니다. 그러나 Text 속성이 ViewModel의 속성에 바인딩되어 있으므로 유효성 검사 규칙이 실행되어 사용자가 비즈니스 규칙을 위반하는 기회조차 없기 전에 Window에 문제가 있음을 나타냅니다.

이 문제가 이전에 해결 되었습니까? 나는 이것을 경험할 수있는 첫 번째 선수가 될 수 없다. 나는 그것이 젊은 선수들을위한 함정이라고 확신한다.

+0

시도해 볼 수 있습니까? UpdateSourceTrigger = "LostFocus" –

+0

유효성 검사 그룹을 만들 수 있으며 사용자가 먼저 일부 필드를 변경하면 유효성 검사 그룹을 활성화 할 수 있습니다. –

+0

@AngelWPF 나는 그것을 시도했다. 윈도우가로드 될 때 초기 바인딩에서 여전히 유효성을 검사합니다. – onefootswill

답변

0

그것은 오랜만이야 내가이 질문을 업데이트해야합니다. 나는 이안 Griffths (AN 오라일리 책)에 의해 WPF 책에서 발견되는 클래스 사용하여 해결 :

<TextBox local:Masking.Mask="^[0-9]*$" IsEnabled="{Binding Path=LocationNumberEnabled}" Grid.Row="1" Grid.Column="3"> 
    <Binding Path="LocationNumber" Mode="TwoWay" UpdateSourceTrigger="LostFocus" NotifyOnValidationError="True" ValidatesOnExceptions="True"> 
     <Binding.ValidationRules> 
      <localValidation:PositiveNumberRule /> 
      <localValidation:RequiredFieldRule /> 
     </Binding.ValidationRules> 
    </Binding>      
</TextBox> 

:

public static class Validator 
{ 
    /// <summary> 
    /// This method forces WPF to validate the child controls of the control passed in as a parameter. 
    /// </summary> 
    /// <param name="parent">Type: DependencyObject. The control which is the descendent root control to validate.</param> 
    /// <returns>Type: bool. The validation result</returns> 
    public static bool IsValid(DependencyObject parent) 
    { 
     // Validate all the bindings on the parent 
     bool valid = true; 
     LocalValueEnumerator localValues = parent.GetLocalValueEnumerator(); 
     while (localValues.MoveNext()) 
     { 
      LocalValueEntry entry = localValues.Current; 
      if (BindingOperations.IsDataBound(parent, entry.Property)) 
      { 
       Binding binding = BindingOperations.GetBinding(parent, entry.Property); 
       foreach (ValidationRule rule in binding.ValidationRules) 
       { 
        ValidationResult result = rule.Validate(parent.GetValue(entry.Property), null); 
        if (!result.IsValid) 
        { 
         BindingExpression expression = BindingOperations.GetBindingExpression(parent, entry.Property); 
         Validation.MarkInvalid(expression, new ValidationError(rule, expression, result.ErrorContent, null)); 
         valid = false; 
        } 
       } 
      } 
     } 

     // Validate all the bindings on the children 
     for (int i = 0; i != VisualTreeHelper.GetChildrenCount(parent); ++i) 
     { 
      DependencyObject child = VisualTreeHelper.GetChild(parent, i); 
      if (!IsValid(child)) 
      { 
       valid = false; 
      } 
     } 

     return valid; 
    } 

} 

다음을보기에, 나는 다음과 같은 구성을 가지고 있었다 매력처럼 일했습니다! 수동으로 유효성을 검사 할 때마다 IsValid 메서드를 호출했습니다. 버튼을 누르십시오.

0

두 가지 패턴이 있습니다. 나는 보통 ISupportInitialize 클래스의 인터페이스를 구현하는데, 이는 BeginInit()EndInit()이라는 메소드를 작성해야한다. 간단히 private bool _isInitializing을 true 또는 false로 설정한다. 뷰 모델에서

또는/당신이 작성/모델/클래스가 시작과 끝의 초기화와 포장 채울 때

var o = new SampleObject(); 
o.BeginInit() 
o.StartDate = DateTime.Now; //just some sample property... 
o.EndInit(); 

그래서 다음 ValidationRule가 호출되는 방법을 따라, 당신의 상태를 확인할 수 있습니다 _isInitializing으로 확인해야하는지 확인하십시오. 당신이 ISupportInitialize 귀찮게하지 않으려는 경우

[CustomValidator("ValidateStartDate")] 
public DateTime StartDate 
{ get ... 
{ 
    set 
    { 
     if(_startDate == value) return; 
     _startDate = value; 
     if(_isInitializing) return; 
     RaisePropertyChange(() => StartDate); 
     }.. 

, 그럼 당신이 필요로하는 모든 값을 전달 :

최근에 내가 사용하고 속성은 그래서 당신이 뭔가를 할 수 PropertyChanged에있는 화재 유효성 검사기 귀하의 속성을 건설하는 동안 속성이 아닙니다. 속성 당신에 처음 게터를 쿼리합니다 바인딩과 값을 얻을 것이다, 아무것도 후 속성 setter을 통해 이동하고 검증받을 :

//c-tor 
public MyObject(DateTime start) 
{ 
    _startDate = start; 
} 
관련 문제