2012-04-19 2 views
0

GroupBox가있는 폼이 있고 여기에 여러 컨트롤 (확인란, 텍스트 상자 및 콤보 상자)이 있습니다.WPF/XAML - 두 번 표시되는 유효성 검사 오류

양식이 속성에 IDataErrorInfo를 구현하는보기 모델에 바인딩되며 사용자가 컨트롤에 잘못된 값을 입력하면 IDataInfo가 잘못된 결과를 반환하고 컨트롤이 일반적인 빨간색 상자로 둘러싸여 오류 메시지가 양식 맨 아래에 표시됩니다.

사실 GroupBox는 필수 값 집합을 나타 내기위한 것입니다. 사용자는 그룹의 확인란 중 하나 이상을 선택해야합니다. 이렇게하지 않으면 개별 컨트롤에 오류가 발생하지 않으며 그룹에 오류가 발생합니다. 그래서 GroupBox에 BindingGroup을 추가하고 아무것도 선택하지 않으면 오류를 반환하는 ValidationRule을 추가했습니다. 그리고 그것은 잘 작동합니다. 아무것도 선택하지 않으면 GroupBox는 일반적인 빨간색 상자로 둘러싸여 있으며 양식 맨 아래에 오류 메시지가 표시됩니다.

내 문제는 GroupBox의 컨트롤 중 하나에서 유효성 검사에 실패하면 두 개의 빨간색 상자가 표시된다는 것입니다. 하나는 컨트롤 주위에, 다른 하나는 GroupBox 주위에 있습니다. 양식 하단의 목록에 두 개의 오류 메시지가 표시됩니다.

BindingGroup이 그룹에 포함 된 모든 항목의 오류를보고하지 않게하려면 어떻게해야합니까?

편집 :

간단한 예 -이 Validation.Errors를 표시하지 않습니다,하지만 당신은 StackPanel의이 포함 된 텍스트 상자가하는 경우, 검증에 실패한 것으로 강조되는 것을 볼 수 있습니다.

XAML :

<Window 
     x:Class="BugHunt5.MainWindow" 
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
     xmlns:local="clr-namespace:BugHunt5" 
     Title="MainWindow" 
     Height="350" 
     Width="525" 
     > 
    <GroupBox 
      Margin="20" 
      Header="This is my group" 
      x:Name="MyGroupBox" 
      > 
     <StackPanel> 
      <StackPanel.BindingGroup> 
       <BindingGroup NotifyOnValidationError="True"> 
       </BindingGroup> 
      </StackPanel.BindingGroup> 
      <TextBox 
        Height="30" 
        Width="100" 
        > 
       <TextBox.Text> 
        <Binding 
          NotifyOnValidationError="True" 
          ValidatesOnDataErrors="True" 
          Path="MyString" 
          UpdateSourceTrigger="PropertyChanged" 
          > 
         <Binding.ValidationRules> 
          <local:NoDecimalsValidationRule ValidatesOnTargetUpdated="True"/> 
         </Binding.ValidationRules> 
        </Binding> 
       </TextBox.Text> 
      </TextBox> 
     </StackPanel> 
    </GroupBox> 
</Window> 

는 C# : 나는 한 번 유사한 문제가 있었다, 그러나이 같은 원인이 때문에이 (에서 논리적 인 방법이 보인다했습니다

public partial class MainWindow : Window 
{ 
    public MainWindow() 
    { 
     InitializeComponent(); 

     this.DataContext = new ViewModel("This should be an integer"); 
    } 
} 
public class ViewModel 
{ 
    public string MyString 
    { get; set; } 
    public ViewModel(string mystring) 
    { this.MyString = mystring; } 
} 
public class NoDecimalsValidationRule : ValidationRule 
{ 
    public override ValidationResult Validate(object value, 
     System.Globalization.CultureInfo cultureInfo) 
    { 
     string myString = value as string; 
     int result; 
     if (!Int32.TryParse(myString, out result)) 
      return new ValidationResult(false, "Must enter integer"); 
     return new ValidationResult(true, null); 
    } 
} 
+1

관련 xaml 및 코드를 추가 할 수 있습니까? –

답변

1

ViewModel.cs

public class ViewModel : INotifyPropertyChanged, IDataErrorInfo 
{ 
    public event PropertyChangedEventHandler PropertyChanged; 

    private bool checked1, checked2; 
    private string myString; 

    public bool Checked1 
    { 
     get { return this.checked1; } 
     set { this.SetValue(ref this.checked1, value, "Checked1"); } 
    } 

    public bool Checked2 
    { 
     get { return this.checked2; } 
     set { this.SetValue(ref this.checked2, value, "Checked2"); } 
    } 

    public string MyString 
    { 
     get { return this.myString; } 
     set { this.SetValue(ref this.myString, value, "MyString"); } 
    } 

    protected virtual void OnPropertyChanged(PropertyChangedEventArgs e) 
    { 
     var handler = this.PropertyChanged; 
     if (handler != null) 
      handler(this, e); 
    } 

    private void SetValue<T>(ref T field, T value, string propertyName) 
    { 
     if (!EqualityComparer<T>.Default.Equals(field, value)) 
     { 
      field = value; 
      this.OnPropertyChanged(new PropertyChangedEventArgs(propertyName)); 
     } 
    } 

    public string Error 
    { 
     get 
     { 
      return this.checked1 == false && this.checked2 == false ? "Must check one value." : string.Empty; 
     } 
    } 

    string IDataErrorInfo.this[string propertyName] 
    { 
     get 
     { 
      switch (propertyName) 
      { 
       case "MyString": 
        int result; 
        return int.TryParse(this.myString, out result) ? string.Empty : "Must enter integer."; 
       default: 
        return string.Empty; 
      } 
     } 
    } 
} 

MainWindow.xaml

<Window x:Class="WpfApplication.MainWindow" 
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
     xmlns:local="clr-namespace:WpfApplication" 
     Title="MainWindow" Height="350" Width="525"> 
    <GroupBox Header="This is my group"> 
     <GroupBox.DataContext> 
      <local:ViewModel MyString="This should be an integer"/> 
     </GroupBox.DataContext> 
     <StackPanel> 
      <StackPanel.BindingGroup> 
       <BindingGroup x:Name="checkedBindingGroup"> 
        <BindingGroup.ValidationRules> 
         <DataErrorValidationRule ValidationStep="ConvertedProposedValue"/> 
        </BindingGroup.ValidationRules> 
       </BindingGroup> 
      </StackPanel.BindingGroup> 
      <CheckBox IsChecked="{Binding Checked1, UpdateSourceTrigger=PropertyChanged, NotifyOnSourceUpdated=True}" Binding.SourceUpdated="OnCheckedSourceUpdated" Content="Checked1"/> 
      <CheckBox IsChecked="{Binding Checked2, UpdateSourceTrigger=PropertyChanged, NotifyOnSourceUpdated=True}" Binding.SourceUpdated="OnCheckedSourceUpdated" Content="Checked2"/> 
      <TextBox Text="{Binding MyString, UpdateSourceTrigger=PropertyChanged, ValidatesOnDataErrors=True, BindingGroupName=Dummy}"/> 
     </StackPanel> 
    </GroupBox> 
</Window> 

MainWindow.xaml.cs를

public partial class MainWindow : Window 
{ 
    public MainWindow() 
    { 
     InitializeComponent(); 
    } 

    private void OnCheckedSourceUpdated(object sender, DataTransferEventArgs e) 
    { 
     this.checkedBindingGroup.ValidateWithoutUpdate(); 
    } 
} 

키 번째 ings :

  • 'MyString'바인딩에서 BindingGroupName을 더미 값으로 설정하면 부모 BindingGroup에 포함되지 않습니다.
  • 'Checked1'및 'Checked2'바인딩은 NotifyOnSourceUpdated를 true로 설정하고 BindingGroup 유효성 검사를 명시 적으로 호출해야하는 Binding.SourceUpdated 이벤트에 이벤트 처리기를 추가해야합니다.
  • BindingGroup.ValidateWithoutUpdate()가 유효성 검사 논리를 실행하도록 BindingGroup의 DataErrorValidationRule의 ValidationStep이 ConvertedProposedValue 또는 RawProposedValue 여야합니다.
+0

그거야. 감사. –

+0

음, 거의 작동합니다. ViewModel.Checked1 또는 ViewModel.Checked2를 변경하면 윈도우의 CheckBox 컨트롤이 업데이트되었지만 GroupBox가 유효성을 다시 검사하지 않습니다. OnCheckedSourceUpdated()가 실행되지 않습니다. –

+0

추가 NotifyOnTargetUpdated = 'Checked 's Bindings'에 해당하고 Binding.TargetUpdated = "OnCheckedSourceUpdated"를 확인란에 추가하십시오. – Stipo

0

역설).

그러나 빨간색 윤곽선을 제거 할 그룹과 연결된 체크 박스 또는 패널의 첨부 된 속성 Validation.ErrorTemplate을 사용하면 약간의 문제가 발생할 수 있습니다.

+0

StackPanel에 StackPanel에 연결된 ValidationRules에 대한 유효성 검사 오류를 표시하려고합니다. TextBox의 ValidationRules에 대한 유효성 검사 오류를 TextBox에 표시하려고합니다. 심지어 유효성 검사 오류가 처리 될 때까지 위쪽으로 전파되기를 원합니다. 내가 싫어하는 것은 유효성 검사 오류가 처리 된 후에도 전파되기를 계속하는 것입니다. –