2011-07-14 25 views
0

自分のビューモデルを取得してカスタムルックアップコントロールを起動し、そのルックアップビューモデルを実質的に表すモーダルダイアログをスローするにはどうすればよいですか?カスタムルックアップコントロールのデータコンテキストは、親レコードビューモデルのものです。ルックアップコントロールには、親レコードビューモデルのlookupviewmodelプロパティにバインドされている別のDependencyPropertyもあります。これはサブlookupviewmodelを表します。ルックアップビューモデルを使用してモーダルダイアログを表示する

方法1)私は、カスタムコントロールがリッスンすることを知っているlookupviewmodelでイベントを使用していました。

メソッド2)ルックアップコントロールのテキストプロパティがバインドされているlookupviewmodelのプロパティの設定ツール内に検証例外をスローしてみました。次に、カスタムルックアップコントロールにErrorEventをフックしました。しかし、このイベント中にユーザーがダイアログ内から値を「修正」すると、元の値が保持されているように見えます。さらに悪いことに、Validation.ClearInvalidを呼び出した後でも、別のErrorEventがまだ起動してエラーが返されます。つまり、すべてのビューモデルが正しいデータを持っているという意味ですべてがうまくいくので、ErrorEventの内部にあるときに、元のデータソースでバインドされたテキストプロパティが変更されているというテキストボックスを無視しているようです。だから私はそのエラーの処理中にエラーを修正することはできませんように思える?

方法2のもう1つの副次的な問題は、Validation.ClearInvalidが赤いエラー境界を削除しないことです。 ErrorTemplateも手動でクリアする必要がありました。そうですか?

私はコントロール内で自然なエラー処理を使用してモーダルダイアログをスローするようにする方法を見つけたいと思います。

答えて

1

これはイベントを使用するものではありません。デカップリングを容易にするためにイベントが存在します。イベントを起こすオブジェクトは、それを聴いているオブジェクトが何をしているのかを知らないでください。あなたはイベントがプロパティの設定者の中からプロパティの値を変更できることを期待しています - 悪いことに、イベントハンドラは処理中のイベントを発生させているプロパティのセッタを呼び出しています。スタックのオーバーフローを避けるためにかなりハックします。

あなたの説明はあまり明確ではありません(あなたが持っている問題と、あなたが同時にしようとしている機能していないソリューションの両方を説明していますが、混乱しています)問題はそれをテストすることができないビューモデルを作成しますので、あなたは、ダイアログをスロービューモデルのコードを持ってしたくないということです

if (IsValid(value)) 
{ 
    _Property = value; 
} 
else 
{ 
    _Property = GetValueFromDialog(); 
} 

:やろうとして再何か以上のようなものですWPFアプリケーションの外部

この場合の回答は、依存性注入を使用することです。 IDialogServiceと呼ばれるインターフェイスを作成します。

interface IDialogService 
{ 
    object GetValueFromDialog(); 
} 

は、今すぐあなたのビューモデルにこのプロパティを追加します。

public IDialogService DialogService { get; set; } 

上記のコードは次のようになります。

if (IsValid(value)) 
{ 
    _Property = value; 
} 
else 
{ 
    _Property = DialogService.GetValueFromDialog(); 
} 

あなたのWPFで使用するためのダイアログサービスを作成します。実際にダイアログをスローして結果を取得するアプリケーションです。アプリケーションで、あなたのビューモデルをインスタンス化すると、次の操作を行います。

MyViewModel vm = new MyViewModel { DialogService = new WpfDialogService(); } 

このように、あなたのアプリケーションで、プロパティのセッターは、ダイアログを設置し、あなたはそれが期待どおりに正確な結果を得ます。上記溶液の本当に多くのスケッチである

MyViewModel vm = new MyViewModel { DialogService = MockDialogService(ExpectedResult) }; 
vm.Property = InvalidValue; 
Assert.AreEqual(ExpectedResult, vm.Property); 

:あなたは、その後のようなテストを書くことができ

public class MockDialogService : IDialogService 
{ 
    private object Result; 

    public MockDialogService(object result) 
    { 
     Result = result; 
    } 

    public object GetValueFromDialog() { return Result; } 
} 

:あなたのユニットテストのために

、このようになりますモックダイアログを作成ソリューションよりも、アプリケーションでダイアログを使用する方法によっては、ここで説明したものよりもはるかに多くの機能が必要になることがあります。 MVVMフレームワークを見てみると、多くの人が1つまたは複数のダイアログサービスを実装していることがわかります。

+0

私はDialogServiceとMediatorについても読んだことがあります。私は、この話題にどのくらいの議論があるかを考えれば、私はちょうど裂かれていると思います。 GUI要素、ビュー、またはビューモデルを投げる責任は誰にありますか? DialogServiceを使用すると、コントロールの使用場所やコントロールが何であっても、プロパティセッターが失敗しても、ダイアログがスローされます。また、デザイナーがダイアログを実装していない場合はどうなりますか?私は、ビューモデルがどのような形でもGUI要素についての形や形を気にしないようにする方法を考え出していました。彼らは検証し、それが失敗すると、ビューは行動を取るかどうかを決定します。 – happyfirst

+0

他の種類のダイアログでDialogServiceが必要になるかもしれませんが、検証ルックアップダイアログではあまり簡単にあきらめたくありませんでした。私が今行ったことは、LookupViewModelに、カスタムルックアップコントロールがINotifyProperyChangedを介して監視しているブールShowModalDialogプロパティがあることです。検証に失敗した場合、ルックアップビューモデルはこれをtrueに設定し、モーダルが表示され、ユーザーは新しい値を選択するかキャンセルすることができます。ダイアログの結果は、ShowModalDialogをtrueに設定したプロパティーセッターに戻ります。結果はtrueですが、検証例外がスローされます。 – happyfirst

+0

ビューモデルはダイアログを要求し、応答を処理します。 WPFダイアログサービスは、本質的にビューの一部です。懸案事項は十分に分かれています。ビューモデルはダイアログの実装方法については何も知らず、ユーザーからの応答が必要なことを知っています。 –

0

MVVMLightまたはPrismのようなフレームワークを使用すると、異なるエンティティ間でペイロードを完全に分離した方法で渡すことができます。 MVVMLightはPrismに比べて非常に軽量です。メッセンジャーのコンセプトは、システム全体のイベントバスとして機能します。同様に、PrismにはEventAggregatorがあります。

関連する問題