2012-11-13 20 views
5

私は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}" /> 

それはあなたの項目を選択すると、選択したオブジェクトのプロパティは、テキストボックスに表示されているオブジェクトを含む単純なはlistBoxです:

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

そして、このように私のXAMLは:私のObservableCollectionは、このようになりますリストボックスオブジェクトにバインドされます。

私のコードをこのように設定すると、私のデータを検証する方法を私が知る唯一の方法はドメインモデルであり、本当に良い習慣ではありません。 ViewModelで取得される前に検証します。基本的に、私はMagazineRepositoryの各プロパティを検証したいと思っています.ViewModelでは、これをどうやってやっていきますか?

PS:私の質問に情報が不足している場合は、このボード(およびプログラミングボード全般)に投稿するのが初めてです。私に知らせてください。

ありがとうございます。

+0

投稿したコードにViewModelが表示されませんが、ViewModelがIDataErrorInfoを実装する典型的な方法は – Alan

+0

です。申し訳ありませんが、暗黙のうちに考えられました。コレクションは私のViewModelにあります。実際にはIDataErrorInfoが実装されていますが、テキストボックスがコレクション内のプロパティを変更するときに、そのプロパティを検証する必要があり、それを正確に行う方法がわかりません。したがって、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クラスを使用する必要があります。例えば。

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はバインドされたプロパティの1つになり、ここで検証を実行できます。

次は、あなたのMainViewModel(あなたのDataContext)です。例えば。

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

のTextBoxが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の同期コピーです。

関連する問題