2014-07-21 10 views
3

최근까지 IDataErrorInfo 인터페이스의 사용자 지정 확장 버전을 사용했습니다. 내 확장 기능을 사용하면 여러 오류를 동시에 처리 할 수 ​​있으며 지금까지는 나에게 매우 도움이되었습니다. 그러나 INotifyDataErrorInfo 인터페이스가 도입됨에 따라 나는 어떤 개선이 있었는지 확인하기 위해 실험을해볼 것이라고 생각했습니다.ValidationAttribute 및 INotifyDataErrorInfo를 사용하여 다른 속성의 유효성을 검사 할 때 하나의 속성에서 유효성 검사를 트리거하는 방법

몇 가지 온라인 자습서를 수행 한 후 System.ComponentModel.DataAnnotations namespace에서 다양한 ValidationAttribute을 사용하고 있습니다. 이 Attribute S를 사용하면 다음과 같은 기본 유효성 검사 규칙을 제공하자 오류 메시지가 바로 적용 ErrorTemplate의에서 사용할 수있는 Valaidation.Errors 수집에 연결로

[MinLength(3, ErrorMessage = "Name must be longer than 3 characters.")] 
public string Name 
{ 
    get { return name; } 
    set { name = value; NotifyPropertyChanged("Name"); Validate("Name", name); } 
} 

초기에는 꽤 좋은 것 같았다. 그러나 내장 된 유효성 검사 규칙의 대부분은 실제로 기본이며 다른 속성 값과 관련된 복잡한 유효성 검사 규칙을 구현해야하는 데 익숙합니다.

그래서 여러 속성과 관련된 간단한 유효성 검사 규칙을 만드는 방법을 알아 보았습니다. 두 개 이상의 필드 중 하나를 설정해야한다는 규칙. 그래서 ValidationAttribute을 확장 한 클래스를 선언하고 온라인 검색을 한 후에 다른 속성 값에 액세스하는 방법을 찾았습니다.

내가 데이터 바인딩 속성에 대한 Validation.Errors 수집 표시된 각 TextBox에 적용되는 사용자 정의 ErrorTemplate와 기본 UI 노크 다음 Name 재산에 내 사용자 지정 Attribute 세트

<ControlTemplate x:Key="ErrorTemplate"> 
    <StackPanel Orientation="Horizontal"> 
     <Border BorderBrush="#4FFF0000" BorderThickness="1" Margin="0,10"> 
      <AdornedElementPlaceholder /> 
     </Border> 
     <Image Name="WarningImage" Source="pack://application:,,,/WpfApplication1;component/Images/Warning_16.png" Margin="5,0,0,0" Tag="{Binding}" /> 
     <Popup PlacementTarget="{Binding ElementName=WarningImage}" Placement="Right" Margin="5,0,0,0" AllowsTransparency="True" IsOpen="True"> 
      <Border BorderThickness="1" BorderBrush="#4FFF0000" CornerRadius="5" Background="White" Padding="5" Margin="10"> 
       <Border.Effect> 
        <DropShadowEffect Color="Red" Opacity="0.5" BlurRadius="15" ShadowDepth="0" /> 
       </Border.Effect> 
       <ItemsControl ItemsSource="{Binding}"> 
        <ItemsControl.ItemTemplate> 
         <DataTemplate> 
          <TextBlock Text="{Binding ErrorContent}" /> 
         </DataTemplate> 
        </ItemsControl.ItemTemplate> 
       </ItemsControl> 
      </Border> 
     </Popup> 
    </StackPanel> 
</ControlTemplate> 

을, 나는에 관리 속성을 설정하지 않았 으면 ValidationResultValidation.Errors 컬렉션에 추가합니다. 그러나 여기에 문제가 있습니다. 다른 특정 속성에 바인딩 된 TextBox 데이터 중 하나에 값을 추가하면 처음에는 오류 메시지가 표시됩니다. TextBox woul 거기에있어.

처음으로 TextBox으로 가서 뭔가를 입력하면 유효성 검사가 작동하므로 값을 삭제하더라도 필수 속성 중 하나가 설정되었음을 여전히 알고있었습니다. 따라서 유효성 검사 코드는 작동하지만 문제는 다른 필수 속성의 속성 변경으로 Name 속성의 유효성 검사가 트리거되지 않는다는 것입니다.

다른 필수 속성에 동일한 사용자 지정 Attribute을 적용한 경우에도 똑같은 문제가 발생했습니다. 각 유효성 검사 오류는 해당 TextBox을 입력 할 때만 사라집니다. 나는 또한 CustomValidationAttribute에 빌드를 시도했는데, 이는 우리가 클래스의 메서드를 호출하여 유효성을 검사 할 수있게했지만 최종 결과는 동일했습니다.

유효성 검사 코드는 작동하지만 다른 필수 속성 변경으로 인해 트리거되지 않습니다. 나는 심지어 Validate 메서드를 호출하여 다른 속성의 이름을 전달하려고 시도했지만 연속 루프에서 끝났다. 질문은 다른 속성의 유효성을 검사 할 때 한 속성의 유효성 검사를 어떻게 트리거 할 수 있습니까?

+0

동일한 샘플을 게시 할 수 있습니까? 나는 그것을 보는 것에 흥미가있다. – pushpraj

+0

와우 ...이 질문은 이미 충분히 길지 않은가요? 나는 온라인에서 모든 것을 얻었습니다 ... 당신은 무엇을보고 싶습니까? 아마도 당신에게 몇 가지 링크를 제공 할 수 있습니까? – Sheridan

+0

질문에는 동일한 내용을 이해할 수있는 충분한 세부 정보가 있습니다. 예제 코드를 모두 작성하여 동일한 코드를 다시 작성하지 않아도되고 문제를 직접 해결할 수 있습니다. – pushpraj

답변

1

여기는 FromTo 속성을 포함하는 클래스에서 내가 한 것입니다. FromTo보다 작거나 같은지 확인하고 싶습니다.

유효성 검사 논리는 CustomValidationAttribute을 사용하여 적용됩니다. 이는 사용자 지정 유효성 검사 속성 클래스를 만드는 것보다 쉽습니다. 클래스의 유형을 알려주고 호출 할 메서드 이름에 유효성 검사 논리가 포함됩니다 (이 메서드는 특정 서명이 있어야합니다). 여기 내 관련 코드는 다음과 같습니다 -

[CustomValidation(typeof(MyModel), "ValidateRange")] 
    public double From 
    { 
     get 
     { 
      return _from; 
     } 
     set 
     { 
      if (_from != value) 
      { 
       _from = value; 
       OnPropertyChanged("From"); 

       // Validate the other side 
       ValidateProperty("To", _to); 
      } 
     } 
    } 

    [CustomValidation(typeof(MyModel), "ValidateRange")] 
    public double To 
    { 
     get 
     { 
      return _to; 
     } 
     set 
     { 
      if (_to != value) 
      { 
       _to = value; 
       OnPropertyChanged("To"); 

       // Validate the other side 
       ValidateProperty("From", _from); 
      } 
     } 
    } 

    private static ValidationResult ValidateRange(ValidationContext validationContext) 
    { 
     var model = validationContext.ObjectInstance as MyModel; 

     if (model.From > model.To) 
     { 
      return new ValidationResult("Invalid range"); 
     } 

     return null; 
    } 

당신이 볼 수 있듯이, "다른"속성의 하나 개의 속성 세터 힘 검증의 코드, 당신이 당신의 마지막 단락에서 언급 한대로 정확하게. 유효성 검사 코드가 Validate()에 대한 다른 호출을 트리거하는 속성 중 하나를 설정하려고 시도하지 않는 한 무한 루프로 들어가야하는 이유는 없습니다.

+0

귀하의 회신에 감사드립니다 ... 이것은 유망 해 보입니다. 나는 오늘 밤 집에 올 때 그것을 시험해 볼 것이다. – Sheridan

+0

제안을 시도한 후에도 전혀 작동하지 않는 것으로 보입니다. 그것은 다른 속성의'TextBox'의'ErrorTemplate's에있는 각 속성에 대한 유효성 검사 오류를 보여줍니다. 그것은 단지 같은 문제이지만 그 반대입니다. – Sheridan

+0

@Sheridan 사과 - 내 모델의 기본 클래스가 OnPropertyChanged() 이벤트 내에서 ValidateProperty()를 호출한다는 사실을 잊어 버렸습니다 (이 상황이 불투명하기 때문에 좋은 디자인이 아닌 것 같습니다). 따라서 위의 코드에서 "From"속성 getter는 먼저 "From"속성 (내부에서 OnPropertyChanged를 통해)의 유효성을 검사 한 다음 ValidateProperty()에 대한 명시 적 호출을 통해 "To"속성의 유효성을 검사합니다. –