単一のTextBox
とその下にいくつかのButton
sがあるビューがあります。ウィンドウがロードされたら、TextBox
にフォーカスを当てます。
MVVMを使用していない場合は、LoadedイベントでTextBox.Focus()
を呼び出すだけです。ただし、私のViewModelは私のビューを認識していません。そのため、ビューのコードビハインドにコードを挿入せずにこれをどのように実現できますか?
編集:答えを読んだ後、私はこのコードをビューxamlに入れることにしました
<DockPanel FocusManager.FocusedElement="{Binding ElementName=MessageTextBox}">
<TextBox Name="MessageTextBox" Text="{Binding Message}"/>
</DockPanel>
これが最初のページフォーカス以外の場合は、ViewModelから制御できるため、おそらくJon Gallowayの回答をお勧めします。
気分が良くなった場合(気分が良くなった場合)、添付プロパティを使用してXamlでこれを行うことができます。
http://msdn.Microsoft.com/en-us/library/system.windows.input.focusmanager.focusedelement.aspx
コードビハインドでできることはすべて、トリックを知っていればXamlで行うことができます。幸い、このトリックを実装する必要はありませんでした。MSが実装しました。
この場合、コードをビューに配置しても問題ないと思います。コントロールにフォーカスを設定すると、アプリケーションのロジックではなく、ユーザーインターフェイスの動作に影響するため、ビューの責任になります。
FocusManagerを使用して、そのプロパティにバインドします。
<Window FocusManager.FocusedElement="{Binding ElementName=ViewModel.FocusedItem}"/>
ViewModelは、ビューに情報を提供するためだけに存在するトランスレータなので、ビューが機能するために必要な情報をVMに追加できます。
実際、UIの問題に焦点を当てていませんか? MVVMは問題を分離することです。モデルに属するものはモデル内にあり、ビューに属するものはビュー内にあり、モデルとビューを一緒にバインドするものはViewModel内にあります(これはもちろん簡略化された説明です)。
これは、UIロジックがビューに残ることを意味します-私の意見では、TextBox.Focus()はこれを実現する適切な方法です。
フォーカスのあるコントロールは非常に「視覚のみ」であると考えるので、コードビハインドにあることには何の問題もありません。
VM=の考え方は、ロジックをビューから遠ざけ、ビューにバインドするモデルのデータバインドに適したバージョンを提供することです。これは、必ずしもallコードは、ロジックコードと、UIに直接関連付けられていないものだけをVMに配置する必要があります。
「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の初期フォーカスがほとんど失敗するため、スレッドの問題を使用する必要があります。
次の解決策は、アプリ全体でグローバルに使用されているため、最適でした。
それが役に立てば幸い...
オラン