2012-11-13 2 views
5

저는 MVVM을 처음 접했고 방금 MVVM 패턴을 따르는 첫 번째 프로젝트를 시작했습니다. IDataErrorInfo 인터페이스를 사용하여 ObservableCollection의 유효성 검사를 시도 할 때 문제가 있습니다. ,MVVM 패턴을 사용하여 ViewModel의 바인딩 된 ObservableCollection 유효성 검사

<ListBox x:Name="listMagazineRepository" 
       Grid.ColumnSpan="2" 
       ItemsSource="{Binding}" 
       DataContext="{Binding MagazineRepository}" 
       DisplayMemberPath="Navn" 
       SelectedItem="{Binding Path=SelectedItem}"/> 

     <TextBox x:Name="txtName" Grid.Row="1" Grid.Column="0" 
        Text="{Binding ElementName=listMagazineRepository, Path=SelectedItem.Navn, UpdateSourceTrigger=PropertyChanged, ValidatesOnDataErrors=True}" /> 
     <TextBox x:Name="txtPrice" Grid.Row="2" Grid.Column="0" 
        Text="{Binding ElementName=listMagazineRepository, Path=SelectedItem.Pris, UpdateSourceTrigger=PropertyChanged, ValidatesOnDataErrors=True}" /> 

그것은 당신이 항목을 선택하면, 선택한 객체의 속성이 텍스트 상자에 표시되는 객체를 포함한 단순한 목록 상자의 :

ObservableCollection<Magazine> magazineRepository; 
    public ObservableCollection<Magazine> MagazineRepository 
    { 
     get { return magazineRepository; } 
     set 
     { 
      if (value != null) 
      { 
       bladRepository = value; 
       OnPropertyChanged("MagazineRepository"); 
      } 
     } 
    } 

그리고 이런 내 XAML : 내 ObservableCollection에는 다음과 같습니다 그런 다음 목록 상자 객체에 바인딩됩니다.

내 코드는 내 코드를 이렇게 설정할 때 내 데이터의 유효성을 검사하는 방법을 도메인 모델에 알려주는 유일한 방법은 실제로 좋은 연습이 아니므로 거기에 도착하기 전에 ViewModel에서 확인하십시오. 기본적으로 ViewModel의 MagazineRepository에서 각 속성의 유효성을 검사하고 싶습니다. 어떻게하면됩니까?

추신 : 내 질문에 정보가 부족한 경우이 게시판 (및 프로그래밍 게시판)에 게시하는 것이 처음입니다. 알려 주시면 필요한 세부 정보를 제공해 드리겠습니다.

고마워요.

+0

게시 한 코드에 ViewModel이 표시되지 않지만 일반적인 방식으로 ViewModel이 IDataErrorInfo를 구현할 수 있습니다. – Alan

+0

죄송합니다. 내 생각에 묵시적이라고 생각했습니다.컬렉션은 실제로 IDataErrorInfo를 구현하는 내 ViewModel에 있지만 텍스트 상자가 컬렉션의 속성을 변경할 때 해당 속성에 대한 유효성을 검사해야하며 정확히 수행 할 방법을 알 수 없습니다. 따라서 각각 2 개의 텍스트 상자가 컬렉션의 속성에 바인딩되어 있으며 해당 속성이 변경되면 IDataErrorInfo를 사용하여 배웠던 방식대로 전체 속성의 유효성을 검사 할 수있는 유효성 검사를 수행해야합니다. –

답변

3

정확하게 이해하면 잡지 개체의 유효성을 검사하고 싶습니다. 그렇다면 뷰 모델에서 해당 클래스를 래핑하고, IDataErrorInfo를 구현하고 잡지 객체를 업데이트 상태로 유지하는 MagazineVM이라고 부르 자. 그런 다음 MagazineVM 목록을보기에 바인드합니다. 아주 간단한 예제로서 :

public class MagazineVM : IDataErrorInfo, INotifyPropertyChanged 
{ 
    private Magazine _magazine; 

    public int FirstMagazineProperty 
    { 
     get { return _magazine.FirstMagazineProperty; } 
     set { _magazine.FirstMagazineProperty = value; RaisePropertyChanged("FirstMagazineProperty"); } 
    } 

    //INotifyPropertyChanged implementation 

    //IDataErrorInfo implementation 
} 
3

첫째로, Dtex에 따르면, Magazine 클래스보다는 MagazineViewModel 클래스를 사용해야합니다. E.G.

public class MagazineViewModel : INotifyPropertyChanged, IDataErrorInfo 
{ 
    private string navn; 
    private string pris; 
    private string error; 

    public string Navn 
    { 
    get { return navn; } 
    set 
    { 
     if (navn != value) 
     { 
     navn = value; 
     RaisePropertyChanged("Navn"); 
     } 
    } 
    } 
    public string Pris 
    { 
    get { return pris; } 
    set 
    { 
     if (pris != value) 
     { 
     pris = value; 
     RaisePropertyChanged("Pris"); 
     } 
    } 
    } 
    public string Error 
    { 
    get { return error; } 
    set 
    { 
     if (error != value) 
     { 
     error = value; 
     RaisePropertyChanged("Error"); 
     } 
    } 
    } 

    public event PropertyChangedEventHandler PropertyChanged; 

    public string this[string columnName] 
    { 
    get 
    { 
     var result = string.Empty; 

     switch (columnName) 
     { 
     case "Pris": 
      if (string.IsNullOrWhiteSpace(Pris)) 
      { 
      result = "Pris is required"; 
      } 
      break; 
     case "Navn": 
      if (string.IsNullOrWhiteSpace(Navn)) 
      { 
      result = "Navn is required"; 
      } 
      break; 
     } 

     return result; 

    } 
    } 

    private void RaisePropertyChanged(string PropertyName) 
    { 
    var e = PropertyChanged; 
    if (e != null) 
    { 
     e(this, new PropertyChangedEventArgs(PropertyName)); 
    } 
    } 

} 

주목할 중요한 속성은 "public string this [string columnName]"입니다. ColumnName은 바인딩 된 속성 중 하나이며 여기에서 유효성 검사를 수행 할 수 있습니다.

다음으로 고려해야 할 것은 MainViewModel (Your DataContext)입니다. E.G.

public class MainViewModel : INotifyPropertyChanged 
{ 
    //Use a readonly observable collection. If you need to reset it use the .Clear() method 
    private readonly ObservableCollection<MagazineViewModel> magazines = new ObservableCollection<MagazineViewModel>(); 

    private MagazineViewModel selectedItem; 

    //Keep the item being edited separate to the selected item 
    private MagazineViewModel itemToEdit; 

    public ObservableCollection<MagazineViewModel> Magazines { get { return magazines; } } 
    public MagazineViewModel SelectedItem 
    { 
    get { return selectedItem; } 
    set 
    { 
     if (selectedItem != value) 
     { 
     selectedItem = value; 
     RaisePropertyChanged("SelectedItem"); 
     //When the selected item changes. Copy it to the ItemToEdit 
     //This keeps the the copy you are editing separate meaning that invalid data isn't committed back to your original view model 
     //You will have to copy the changes back to your original view model at some stage) 
     ItemToEdit = Copy(SelectedItem); 
     } 
    } 
    } 
    public MagazineViewModel ItemToEdit 
    { 
    get { return itemToEdit; } 
    set 
    { 
     if (itemToEdit != value) 
     { 
     itemToEdit = value; 
     RaisePropertyChanged("ItemToEdit"); 
     } 
    } 
    } 

    public event PropertyChangedEventHandler PropertyChanged; 

    public MainViewModel() 
    { 
    //Ctor... 
    } 

    //Create a copy of a MagazineViewModel 
    private MagazineViewModel Copy(MagazineViewModel ToCopy) 
    { 
    var vm = new MagazineViewModel(); 
    vm.Navn = ToCopy.Navn; 
    vm.Pris = ToCopy.Pris; 
    return vm; 
    } 

    private void RaisePropertyChanged(string PropertyName) 
    { 
    //... 
    } 
} 

여기서 누락 된 유일한 점은 변경 사항을 원래의보기 모델에 다시 복사하는 것입니다. 선택한 항목이 변경되기 전에 (ItemToEdit가 유효한 경우)이를 수행하거나 ItemToEdit이 유효 할 때만 사용 가능한 커밋 단추를 가질 수 있습니다. 원본 뷰 모델이 유효하지 않은 상태가되도록 허용하면 복사에 대해 걱정할 필요가 없습니다.

마지막으로 XAML

암시 적 스타일은 텍스트 상자가 ItemToEdit에 결합 오류 툴팁

<Style 
    TargetType="{x:Type TextBox}"> 
    <Setter 
    Property="ToolTip" 
    Value="{Binding RelativeSource={RelativeSource Self}, Path=(Validation.Errors)[0].ErrorContent}" /> 
</Style> 

그리고 컨트롤과 바인딩

<ListBox 
    ItemsSource="{Binding Magazines}" 
    DisplayMemberPath="Navn" 
    SelectedItem="{Binding Path=SelectedItem, Mode=TwoWay}" /> 
<TextBox 
    Margin="5" 
    x:Name="txtName" 
    Grid.Row="1" 
    Grid.Column="0" 
    Text="{Binding ItemToEdit.Navn, UpdateSourceTrigger=PropertyChanged, ValidatesOnDataErrors=True}" /> 
<TextBox 
    Margin="5" 
    x:Name="txtPrice" 
    Grid.Row="2" 
    Grid.Column="0" 
    Text="{Binding ItemToEdit.Pris, UpdateSourceTrigger=PropertyChanged, ValidatesOnDataErrors=True}" /> 

를 표시합니다. ItemToEdit은 SelectedItem의 동기화되지 않은 사본입니다.

관련 문제