2012-02-21 56 views
1

以下のコードを使用して、無効なセルエントリをトラップできます。食料品買い物リストのこの単純な例では、GroceryItem.Nameを記入するだけで済みます。重複したエントリを防ぐためのDatagrid検証

私が今したいことは、そのエントリーがまだ存在していないことを検証する機能を追加することです。既に存在する場合は、同じセルエントリを強調表示したいが、適切なメッセージを表示したい。したがって、ユーザーが「Eggs」を再度入力すると、セルのエラーメッセージは「Eggs is already on the list」でなければなりません。

アイテムビューモデルはコンテナビューモデルについて知ってはいけません。したがって、「名前」プロパティのセルの検証中に重複したエントリがどこで確認できますか?コレクション

enter image description here

項目は

public class GroceryItem : ObservableObject, IDataErrorInfo 
{ 

    #region Properties 

    /// <summary>The name of the grocery item.</summary> 
    public string Name 
    { 
     get { return _name; } 

     set 
     { 
      _name = value; 
      RaisePropertyChangedEvent("Name"); 
     } 
    } 
    private string _name; 

    #endregion 

    #region Implementation of IDataErrorInfo 

    public string this[string columnName] { 
     get { 
      if (columnName == "Name") { 
       if (string.IsNullOrEmpty(Name)) 
        return "The name of the item to buy must be entered"; 
      } 

      return string.Empty; 
     } 
    } 

    public string Error { get { ... } } 

    #endregion 
} 

ビューモデルは、コレクションのDataGridのバインディング

public class MainWindowViewModel : ViewModelBase 
{ 

    /// <summary>A grocery list.</summary> 
    public ObservableCollection<GroceryItem> GroceryList 
    { 
     get { return _groceryList; } 

     set 
     { 
      _groceryList = value; 
      RaisePropertyChangedEvent("GroceryList"); 
     } 
    } 
    private ObservableCollection<GroceryItem> _groceryList; 

    /// <summary>The currently-selected grocery item.</summary> 
    public GroceryItem SelectedItem { get; [UsedImplicitly] set; } 

    void OnGroceryListChanged(object sender, NotifyCollectionChangedEventArgs e) 
    { 
     // doing non-validation stuff 
    } 
} 

ビューを保持

<DataGrid 
    x:Name="MainGrid" 
    ItemsSource="{Binding GroceryList}" 
    SelectedItem="{Binding SelectedItem}" 
    ...    
    > 
    <DataGrid.Resources> 
     <Style TargetType="{x:Type DataGridCell}"> 
      <Setter Property="TextBlock.ToolTip" 
      Value="{Binding Error}" /> 
     </Style> 
    </DataGrid.Resources> 

    <DataGrid.Columns> 
     ... 
     <DataGridTextColumn Header="Item" Width="*" Binding="{Binding Name, ValidatesOnDataErrors=True}" IsReadOnly="false" /> 
    </DataGrid.Columns> 
</DataGrid> 

答えて

1

私はドン」これがMVVMに違反するかどうかは知っていますが、私がやる方法は別のコンストラクタのGroceryItemにGroceryListを渡し、GroceryItemのprivate ObservableCollection groceryListに保存することです。それはGroceryListへの畏敬の念にすぎないので、オーバーヘッドが増えません。

public class GroceryItem : ObservableObject, IDataErrorInfo 
    { 
     private ObservableCollection<GroceryItem> groceryList; 

     public void GroceryItem(string Name, ObservableCollection<GroceryItem> GroceryList) 
     { 
       name = Name; 
       groceryList = GroceryList; 
       // now you can use groceryList in validation 
     } 
    } 
+0

GroceryItemにデフォルトのctorが必要なので、DataGridに自動的に行を追加させることはできません。コレクションをコントロールするメインのビューモデルにAddCommandが必要ですが、はい、これは明確な可能性に同意します。 – Berryl

+0

あなたのアイデアはMVVMについて何も違反していません。私はおそらく、すべての通知がすでにデータバインディングから来ていると思っています。私が見ていないよりゆるやかに結合されたソリューションを利用できるかもしれません。 Cheers – Berryl

+0

デフォルトでは、アイテムはコレクションのメンバーであることを実際には認識していません。コレクションへの参照を渡すことは、私が考えることができるアイテムからコレクションにアクセスするための最も邪魔な方法であり、私はそれを多く使用します。 – Paparazzi

関連する問題