2012-04-03 2 views
15

많은 컨트롤이있는 MVVM 기반 Window가 있고 모델에 IDataErrorInfo이 있습니다.IDataErrorInfo를 사용하여 ViewModel에서 View에 유효성 검사 오류 업데이트를 적용하는 방법은 무엇입니까?

또한 속성을 분석하여 유효성 검사를 수행하는 SaveCommand 단추가 있습니다.

특정 컨트롤의 값을 변경하거나 PropertyChanged를 사용하여 해당 속성의 변경 사항을 알릴 때만 뷰에 오류 주변의 기본 빨간색 테두리가 으로 표시됩니다.

컨트롤을 건드리지 않은 경우에도보기가 모든 유효성 검사 오류를 표시하도록하려면 어떻게해야합니까?

모든 유효성 검사 바인딩에는 ValidatesOnDataErrors=True, NotifyOnValidationError=True이 포함됩니다.

모든 오류가있는 집계 상자가있는 것이 하나의 해결책이지만 컨트롤 단위로 오류를 표시하는 것이 좋습니다.

ViewModel의 각 바운드 속성에 대해 Model.NotifyPropertyChanged을 트리거하고 싶지 않습니다.

Silverlight가 아닌 WPF 4.0을 사용하므로 INotifyDataErrorInfo이 작동하지 않습니다.

답변

12

바인딩하는 속성에 대해 변경된 속성을 올리고 싶지는 않지만 실제로이 작업을 수행하는 가장 간단한 방법입니다. 매개 변수없이 PropertyChanged를 호출하면 viewmodel의 모든 속성이 발생합니다.

myControl.GetBindingExpression(ControlType.ControlProperty).UpdateSource(); 
+2

PropertyChanged를 사용해 주셔서 감사합니다. 나는 그것이 가능하다는 것을 몰랐다. 이 주제에 대한 또 다른 토론을 찾았습니다. http://stackoverflow.com/questions/1135012/wpf-mvvm-can-a-single-propertychanged-update-all-the-data-bindings-of-a-datate if 누구든지 관심이있다. 누군가가 단일의 간단한 viewModel을 가지고 있다면 이것은 좋은 대답입니다.그러나 중첩 된 ViewModels 함께 복잡한보기를 가지고 있으므로 코드를 작성하여 각 중첩 된 바인딩 된 Model/ViewModel INotifyPropertyChanged 구현하는 번 한 번 호출해야합니다 – surfen

+0

하나의보기 만 관련된 업데이트가 필요한 경우이 트릭을 알고 좋다 특정의 ViewModel에 대해서 – surfen

+0

myControl.GetBindingExpression (ControlType.ControlProperty) .UpdateTarget(); 소스 속성을 업데이트하지 않고 실제로 유효성을 검사합니다. – r41n

2

내가 지금까지 발견 한 최선의 해결책은 DataContext를 null로 변경하고 ViewModel의 인스턴스로 되돌려 놓는 것입니다. 데이터가이 트릭 후 손실되지 않습니다 있는지 확인하는 것이 좋습니다

public void ForceUpdateErrors() { 
    var tmpInnerVM = _mainViewModel.InnerViewModel; 
    _mainViewModel.InnerViewModel = null; 
    _mainViewModel.InnerViewModel = tmpInnerVM; 
} 

:

이것은 InnerViewModel에 바인딩 DataContext이있는 뷰 컨트롤에 대한 업데이트를 트리거합니다. 이 코드가 null로 ComboBox.SelectedItem에 대한 소스 업데이트를 트리거 한 경우가 있었지만 해결할 수있었습니다. 리소스 기반 BindingProxy를 사용하고 제어 계층 전반에 걸쳐 DataContext=null 전파 순서로 인해 발생했습니다.

1

이 '해킹'는 InotifyChanged 이벤트를 강제로 그냥 자신을 해당 컨트롤을 다시 할당, 일시적으로 나를 위해 일한 :

또한이 같은 모든 컨트롤에 바인딩 (힘의 재 검증)를 업데이트 할 수 있습니다 함유량. 바인딩의 HasError 함수를 평가하기 전에 수행하십시오. 예를 들어 텍스트 상자가 될 것이다 :

((TextBox)child).Text = ((TextBox)child).Text; 

그리고 완전한 예를

 public bool Validate() 
    {   
     bool hasErr = false; 

     for (int i = 0; i != VisualTreeHelper.GetChildrenCount(grd); ++i) 
     { 
      DependencyObject child = VisualTreeHelper.GetChild(grd, i); 
      if (child is TextBox) 
      { 
       bool pp = BindingOperations.IsDataBound(child, TextBox.TextProperty); 
       if (pp) 
       { 

        ((TextBox)child).Text = ((TextBox)child).Text; 

        hasErr = BindingOperations.GetBindingExpression(child, TextBox.TextProperty).HasError; 
        System.Collections.ObjectModel.ReadOnlyCollection<ValidationError> errors = BindingOperations.GetBindingExpression(child, TextBox.TextProperty).ValidationErrors; 
        if (hasErr) 
        { 
         main.BottomText.Foreground = Brushes.Red; 
         main.BottomText.Text = BindingOperations.GetBinding(child, TextBox.TextProperty).Path.Path.Replace('.', ' ') + ": " + errors[0].ErrorContent.ToString(); 
         return false; 
        } 
       } 
      } 
      if (child is DatePicker) 
      { 
       ...      
      } 
     } 

     return true; 
    } 
(I 듣고 전에이 사실 MVVM하지, 내가 직접 코드 snipet을 보여주는의 편의를 위해 그리드에 핸들을 가지고)
관련 문제