WPF MVVM焦点字段加载

Sha*_*owe 48 c# wpf textbox focus mvvm

我有一个View,它下面有一个TextBox和几个Button.当窗口加载时我希望它TextBox具有焦点.

如果我没有使用MVVM,我只会调用TextBox.Focus()Loaded事件.但是我的ViewModel不了解我的视图,那么如何在不将代码放入视图的代码隐藏的情况下完成此操作呢?

编辑:在阅读答案后,我决定将此代码放在xaml视图中

<DockPanel FocusManager.FocusedElement="{Binding ElementName=MessageTextBox}">    
    <TextBox Name="MessageTextBox" Text="{Binding Message}"/>
</DockPanel>
Run Code Online (Sandbox Code Playgroud)

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

And*_*mes 50

如果它让你感觉更好(它让我感觉更好)你可以使用附加属性在Xaml中执行此操作:

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

如果你知道技巧,你可以在Xaml中做任何你可以在代码隐藏中做的事情.幸运的是,你没有必要实现这个技巧 - MS为你做了.

  • 在阅读了其他一些答案后,我不确定代码是否属于ViewModel.它似乎与视图直接相关.如果我有一个更复杂的页面,实际上基于其他可能有意义的事件移动焦点.这说它仍然是一个很好的技巧. (3认同)
  • Galloway的建议允许您从ViewModel控制焦点......您也可以仔细研究它. (2认同)

Mar*_*ris 14

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

  • 我认为,一旦我将MVVM理念从"无代码背后"改为"最低限度和相关代码背后",我的生活就变得容易多了.我没有听说过Anderson Imes所提到的附加属性,这听起来很好地解决了后面的代码给你带来的不好的味道,但是不要害怕把*合法的*,非逻辑代码放在UI. (15认同)
  • 我非常赞同你.我认为从视图中删除代码是不合理的.重要的是视图中的代码应该与UI非常相关.VM中的代码包含与模型有关的状态和其他逻辑.石蕊试验是代码是否可以/应该进行测试.视图中的代码无法测试. (4认同)

Jon*_*way 9

  1. 在ViewModel中有一个属性,指示哪个是当前关注的元素.
  2. 使用FocusManager绑定到该属性.

    <Window FocusManager.FocusedElement="{Binding ElementName=ViewModel.FocusedItem}"/>
    
    Run Code Online (Sandbox Code Playgroud)

您的ViewModel是一个翻译器,仅用于向View提供信息,因此您可以向View中需要运行的VM添加任何信息.

  • 恕我直言,VM应该没有关于实际视图实现中的控件名称或类型的信息.相反,我让视图侦听来自VM的属性更改通知,然后让它处理它.例如,ActivateNameField变为true .. View查找相关控件并将焦点设置为它. (9认同)
  • 但是,您必须为所有元素命名并在VM中使用该名称.如果视图绑定到VM中的项目集合,则无效. (4认同)

mac*_*kow 8

实际上,是不是关注UI关注?MVVM是关于分离关注点 - 属于模型的东西在模型中,属于视图的是什么,以及将模型和视图绑定在一起的是ViewModel(这当然是过于简化的描述).

这意味着,UI逻辑保留在View中 - TextBox.Focus()在我看来是实现这一目标的恰当方式.


Ste*_*ins 5

我认为具有焦点的控件非常“仅可视”,因此在代码后面不会有任何问题。

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