加载WPF MVVM焦点字段

我有一个视图,它下面有一个单独的TextBox和一对Button 。 当窗口加载时,我希望TextBox有焦点。

如果我不使用MVVM,我只需要在Loaded事件中调用TextBox.Focus() 。 然而,我的ViewModel不知道我的看法,所以我怎么能做到这一点,而不是把代码放到我的视图的代码隐藏?

编辑:在阅读答案后,我决定把这个代码在视图xaml

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

如果这不是初始页面焦点,我可能会推荐Jon Galloway的答案,因为它可以从ViewModel控制。

如果它让你感觉更好(这让我感觉更好),你可以使用附加属性在Xaml中做到这一点:

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

如果你知道这些技巧,你可以在代码隐藏中做任何事情。 幸运的是,你不必执行这个技巧 – MS为你做了。

在这种情况下,我认为可以将代码放入视图中。 将焦点设置为控件会影响用户界面的行为而不是应用程序的逻辑,因此是视图的责任。

  1. 在你的ViewModel中有一个属性,指明哪个是当前焦点的元素。
  2. 使用FocusManager绑定到该属性。

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

你的ViewModel是一个翻译器,它只是为View提供信息,所以你可以添加任何信息到View需要的VM上。

其实,是不是重点关注UI? MVVM是关于分离关注的 – 模型中属于模型,属于视图的是在视图中,而模型和视图一起绑定在ViewModel中(这当然是过于简单的描述)。

这意味着UI逻辑保留在View中 – 在我看来,TextBox.Focus()是适当的方式来实现这一点。

我认为重点控制是非常“可视的”,所以不会有任何问题,在后面的代码。

虚拟机的想法是将逻辑从View中移走,并为要绑定的视图提供数据绑定友好的模型版本。 这并不一定意味着所有的代码都应该存在于虚拟机中,只要是逻辑代码以及任何不直接绑定到UI的东西。

在“WPF初始焦点梦魇”之后,根据堆栈上的一些答案,以下certificate对我来说是最好的解决scheme。

首先,添加你的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的初始焦点大多因为一些框架竞争条件而失败。

我发现以下解决scheme是最好的,因为它是全球使用整个应用程序。

希望能帮助到你…

奥兰