2

ゴール:

datagid の lostfocus イベントを全体として認識/キャプチャし、それをビュー モデルの ICommand にバインドする WPF/MVVM (正確には mvvm-light) アプリケーションがあります。

問題は、データグリッド内のコントロールがフォーカスを失い、データグリッド自体がフォーカスを失うたびに、lost focus イベントが発生することです。私のアプリケーションでは、viewModle の「HasErrors」プロパティが true の場合に、ユーザーが現在のビューから「移動」しようとすると、datagrid lostfocus イベント/コマンドで警告 (MVVM タイプのメッセージ ボックス) をスローします。その結果、ユーザーがデータグリッド内のコントロール間を移動しても、ユーザーはこのエラー/警告を受け取ります。データグリッド全体がフォーカスを失った場合にのみ必要です。

これが難しい理由: 簡単に言えば、これが難しいのは MVVM を使用しているからです。通常、コード ビハインド ロストフォーカス イベントで FocusManager をチェックして、現在フォーカスされている要素を取得し、データグリッド内にあるかどうかを確認できます (概要はこちら)。

質問:

この問題に対する MVVM 標準ソリューションはありますか? 私はコードビハインドが決してないほど盲目的に死ぬほど難しいMVVMではありません.

私が試したこと:

FIRST - コマンドごとに異なるコマンド パラメータを使用しようとしました。すなわち:

<DataGrid>
    <i:Interaction.Triggers>
        <i:EventTrigger EventName="LostFocus">
            <cmd:EventToCommand Command="{Binding DataContext.PreNavigateValidateCommand, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type UserControl}}}"
            CommandParameter="DataGridLostFocus"/>
        </i:EventTrigger>
    </i:Interaction.Triggers>
</DataGrid>

およびデータグリッドのコントロール用

<DataGrid>
    <i:Interaction.Triggers>
        <i:EventTrigger EventName="LostFocus">
            <cmd:EventToCommand Command="{Binding DataContext.LostFocusValidateCommand, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type UserControl}}}"
             CommandParameter="ControlostFocus"/>
        </i:EventTrigger>
    </i:Interaction.Triggers>
</DataGrid>

DataGridLostFocus と ControlLostFocus のコマンド パラメータの違いに注意してください。しかし、何が起こるかというと、これらのコマンドが 2 回発生するということです。各コマンド パラメーターに対して 1 回で、最初に control lostfocus が発生し、その後に datadrid lostfocus が発生します。

2つ目 -コマンドのプロパティや名前が異なることに気付くでしょう。コマンドを別のコマンド オブジェクトにバインドしても、この問題は解決しませんでした。両方のコマンドが、上記と同じ順序で呼び出されます。

3番目 データグリッドはグリッドの内側にあり、グリッドはユーザーコントロールの内側にあるエキスパンダーの内側にあります。ビジュアル ツリーをこれら 3 つの要素にバインドする ICommand トリガーを移動してみました。ロスト フォーカス イベントは、これら 3 つの「親」オブジェクトのいずれかに配置された場合でも、同じように発生します。


ビューモデルの HasErrors プロパティのこのエラートリガーを処理する方法を完全に再考するか、機能する別のイベントを見つける必要があると考え始めています。

MVVM標準に引き続き準拠しているデータグリッド全体のフォーカス喪失イベントを分離する際の助けをいただければ幸いです。

ありがとう

4

1 に答える 1

8

私たち開発者のほとんど (私自身を含む) は、長い間 MVVM を広く誤解してきたと思います。

RelativeSourceコード ビハインドをまったく回避する傾向があるため、ビュー レイヤーにコード/ロジックを配置しない場合、バインディング、コンバーター、 XAML が存在しないことを実際に理解していないため、これはどこでも不要な過度の複雑化につながります。全て。

MVVM の本当の精神はseparate、ビューにコードが含まれないようにすることではなく、UI からロジックを作成することです。

Focusこれは、コード ビハインドを介して問題 (これは純粋にビューの問題です) を解決できること、および解決すべきであることを意味します。ただし、これは、コード ビハインドにアプリケーション/ビジネス ロジックを配置するという意味ではありません。

簡単に言えば、UI イベントをコード ビハインドで処理し、ロジックを ViewModel にデリゲートするだけです。

private void DataGrid_LostFocus(object sender, RoutedEventArgs e)
{
    if (DataGrid.IsKeyboardFocusWithin) //or whatever UI condition
    {
        //Resolve the ViewModel via DI, constructor injection or whatever. Then:
        ViewModel.DoMyBusinessLogic();
    }
}

私が何を意味するか分かりますか?ここにビジネスロジックを配置していません。ビジネス ロジックは引き続き ViewModel / Model にありますが、View 関連のコード ( Focus) は Code Behind に配置されます。

また、これはまさに何をするかCommandsです。ビュー内の何らかのイベントに反応してから、ViewModel 内の何らかのメソッドを呼び出しますね。

これにより、私たちが慣れ親しんできた厳密なコードビハインド禁止ポリシーによって引き起こされる苦痛が本当に軽減されると思います。

これについて他の方の意見も聞きたいです

于 2013-06-17T04:20:31.393 に答える