2

リレー コマンドとデータ バインドとして MVVM を使用して、C# WPF で単純なデータベース アプリケーションを作成しています。私が使用するデータベース コンテンツのインメモリ ストレージにはObservableCollection、次のように Datagrid にバインドされます。

<DataGrid ItemsSource="{Binding Path=Softwares, Mode=OneWay}" SelectedItem="{Binding Path=SoftwareSelection, Mode=TwoWay}">

項目が選択されると、ユーザーはそれを編集することを選択できます。編集のために、特定のエンティティのデータを含む一連のテキスト ボックスを含むフォームが開かれます。すべてのフィールドは を使用して検証IDataErrorInfoされます。すべてのテキスト ボックスが有効でない限り、[OK] ボタンは有効になっていないため、コレクションやデータベースに変更を保存することはできません。

テキストボックスの例は次のようになります。

<TextBox Text="{Binding Name, Mode=TwoWay, ValidatesOnDataErrors=True, UpdateSourceTrigger=PropertyChanged, ValidatesOnExceptions=True}"/>

しかし、難しいのは、テキスト ボックスの値を変更してからウィンドウを閉じると、新しい値が に反映されるObservableCollectionことです。これは望ましくありません。そのような行動を防ぐ方法はありますか?ボタンをクリックした後にのみデータバインディングが機能するようにします。それ以外の場合、データバインディングはうまく機能するため、クリック後にボタンが (無効化/有効化) 有効になり、データベースとコレクションへの変更が反映されます。どちらのビューも異なる ViewModel によって処理され、ビュー間のデータはイベントの発生によって渡されます。

ItemsSource バインディングに追加しようとしましたDataGrid UpdateSourceTrigger=Explicitが、役に立ちませんでした。おそらく、いくつかのアプリケーション ロジックが不足していますか?

ご助力ありがとうございます。

4

3 に答える 3

1

これは、ほとんどの WPF 開発者が想定の誤りを犯す場所です。

MVVM では、ダーティ データを に格納できます。これViewModelが VM のレイヤーの目的です。ViewfromModelの視点を模倣しておりView、 がエラーになっているためViewModel、 もエラーになります。それは完全に有効です。

そうは言っても、疑問は残ります

ObservableCollection に一時/ダーティデータが流れないようにするにはどうすればよいでしょうか?

ふたつのやり方...

  1. あなたObservableCollectionがあなたのモデルクラスに固有のものである場合(たとえばMyItem、あなたのモデルクラス(MyItem)がエンティティクラス\ DALクラス\ NHibernateクラスである場合)と呼ばれるクラスのラッパーを作成し、MyItem代わりViewModelMyItemに.ObservableCollection<MyItem>ObservableCollection<ViewModelMyItem>

    このようにして、あなたからのダーティデータはView内部にあり、ボタンがクリックされた場合にViewModelMyItemのみ、合法的にモデルクラスに戻すことができます ( MyItem) 。Saveつまり、Save Commandのデリゲートで、 の検証が問題なければ、 のプロパティを のプロパティにExecute()コピーまたは複製できます。ViewModelMyItemItemViewModelMyItem

    クラス/クラス/クライアントモデルクラスの場合、一時的/ダーティな情報を前もってフィルタリングしているため、常に有効なデータのみになりItemます。EntityTypeNHibernateWCFViewModelMyItem

  2. Explicitバインディングモデルを使用できます。明示的に呼び出されない限り、TwoWayデータがソースに戻るのを止めます。ItemBindingExpressions.UpdateSource()

    ViewModelしかし、私によると、 UI が表示しているものがないため、これは MVVM を簡単に打ち負かします! ただし、 * Attached Behavior *を使用して、MVVM スペースにとどまることで明示的なバインディングを制御できます。

これが役立つかどうか教えてください!

于 2012-05-15T05:21:50.830 に答える
0

Binding Mode を Explicit に設定するには、バインディング式の UpdateSource() メソッドを呼び出して、変更をモデルに送り返す必要があります。DataGrid のバインディングで Explicit を設定したとだけ述べたので、モデルに直接バインドされているプロパティにそのモードが明示的に設定されていることを確認するだけでよいと思います。上記の場合、TextBox の Text Binding など。これで問題が解決する可能性がありますが、各ターゲットの BindingExpression で UpdateSource() を何らかの方法で呼び出す必要があります。

主流の ORM (EF、Linq to SQL など) の 1 つを使用している場合、エンティティは自動的に INotifyPropertyChanged と INotifyPropertyChanging を実装する可能性があります。単一のインスタンスへの参照を共有しているため、編集のすべての変更がメイン ビューとそのインスタンスへのバインディングに反映されます。より汚れた代替手段として、同じタイプの別のインスタンスを作成し、ウィンドウのダイアログ結果が true の場合に値を手動でコピーすることができます。

最初のアプローチではバインディングを手動で更新する必要があり、2 番目のアプローチでは Edit のインスタンスから値を手動で更新する必要があります。

いくつかのコードを使用して、特定のアプローチを支援できます。

于 2012-05-14T23:49:57.547 に答える