web-dev-qa-db-ja.com

ロード時のWPF MVVMフォーカスフィールド

単一のTextBoxとその下にいくつかのButtonsがあるビューがあります。ウィンドウがロードされたら、TextBoxにフォーカスを当てます。

MVVMを使用していない場合は、LoadedイベントでTextBox.Focus()を呼び出すだけです。ただし、私のViewModelは私のビューを認識していません。そのため、ビューのコードビハインドにコードを挿入せずにこれをどのように実現できますか?

編集:答えを読んだ後、私はこのコードをビューxamlに入れることにしました

<DockPanel FocusManager.FocusedElement="{Binding ElementName=MessageTextBox}">    
    <TextBox Name="MessageTextBox" Text="{Binding Message}"/>
</DockPanel>

これが最初のページフォーカス以外の場合は、ViewModelから制御できるため、おそらくJon Gallowayの回答をお勧めします。

48
Shaun Bowe

気分が良くなった場合(気分が良くなった場合)、添付プロパティを使用してXamlでこれを行うことができます。

http://msdn.Microsoft.com/en-us/library/system.windows.input.focusmanager.focusedelement.aspx

コードビハインドでできることはすべて、トリックを知っていればXamlで行うことができます。幸い、このトリックを実装する必要はありませんでした。MSが実装しました。

50
Anderson Imes

この場合、コードをビューに配置しても問題ないと思います。コントロールにフォーカスを設定すると、アプリケーションのロジックではなく、ユーザーインターフェイスの動作に影響するため、ビューの責任になります。

14
Martin Harris
  1. ViewModelに、現在フォーカスされている要素を示すプロパティがあります。
  2. FocusManagerを使用して、そのプロパティにバインドします。

    <Window FocusManager.FocusedElement="{Binding ElementName=ViewModel.FocusedItem}"/>
    

ViewModelは、ビューに情報を提供するためだけに存在するトランスレータなので、ビューが機能するために必要な情報をVMに追加できます。

9
Jon Galloway

実際、UIの問題に焦点を当てていませんか? MVVMは問題を分離することです。モデルに属するものはモデル内にあり、ビューに属するものはビュー内にあり、モデルとビューを一緒にバインドするものはViewModel内にあります(これはもちろん簡略化された説明です)。

これは、UIロジックがビューに残ることを意味します-私の意見では、TextBox.Focus()はこれを実現する適切な方法です。

8
maciejkow

フォーカスのあるコントロールは非常に「視覚のみ」であると考えるので、コードビハインドにあることには何の問題もありません。

VM=の考え方は、ロジックをビューから遠ざけ、ビューにバインドするモデルのデータバインドに適したバージョンを提供することです。これは、必ずしもallコードは、ロジックコードと、UIに直接関連付けられていないものだけをVMに配置する必要があります。

4
Steven Robbins

「WPF初期フォーカスの悪夢」を経験した後、スタックのいくつかの回答に基づいて、以下が最良の解決策であることが証明されました。

まず、App.xaml OnStartup()に以下を追加します。

EventManager.RegisterClassHandler(typeof(Window), Window.LoadedEvent,
          new RoutedEventHandler(WindowLoaded));

次に、App.xamlにも「WindowLoaded」イベントを追加します。

void WindowLoaded(object sender, RoutedEventArgs e)
    {
        var window = e.Source as Window;
        System.Threading.Thread.Sleep(100);
        window.Dispatcher.Invoke(
        new Action(() =>
        {
            window.MoveFocus(new TraversalRequest(FocusNavigationDirection.First));

        }));
    }

一部のフレームワークの競合状態により、WPFの初期フォーカスがほとんど失敗するため、スレッドの問題を使用する必要があります。

次の解決策は、アプリ全体でグローバルに使用されているため、最適でした。

それが役に立てば幸い...

オラン

2
OrPaz