如何使用MVVM将焦点设置到文本框?

如何从ViewModel wpf中聚焦文本框?

 

您可以通过向ViewModel添加属性(或使用现有属性)来执行此操作,该属性指示何时应该发生SetFocus,但View应负责实际设置焦点,因为这纯粹与View相关。

您可以使用DataTrigger执行此操作。

视图:

       

视图模型:

 // When you think the view should set focus on a control this.UserShouldEditValueNow = true; 

通过使用布尔ViewModel属性“UserShouldEditValueNow”简化了上面的示例。 您可以将这样的属性添加到ViewModel或使用一些指示此状态的其他exising属性。

注意:那么为什么在MVVM中这样做呢? 一个原因是,假设View作者决定用ComboBox替换TextBox,或者甚至更好,假设你的属性是一个整数值,既有一个TextBox来查看/编辑这个数字另一个是Slider作为另一种编辑相同值的方法。 ,两个控件都绑定到同一个属性…… ViewModel将如何知道要设置焦点的控件? (当它甚至不知道哪个控件或控件首先绑定到它时)这样View可以通过更改DataTrigger Setter中的ElementName绑定目标来选择要关注的控件。

快乐的编码!

你应该问自己的问题是“为什么我的ViewModel需要知道哪个控件有焦点?”

我认为焦点是一个只有视图的属性; 它是一个交互属性,与概念状态无关。 这类似于控件的背景颜色:为什么要在VM中表示它? 如果您需要以自定义方式管理焦点,则最好使用视图级对象来完成工作。

在父控件中,添加以下属性:

 FocusManager.FocusedElement="{Binding ElementName=PropertySearch}" 

虽然纯粹主义者可能会主张将其从VM中删除,但有时可能会从VM中执行此操作。

我的方法是使视图实现一个接口,将该接口传递给ViewModel,然后让VM调用接口上的方法。

例:

 public interface IFocusContainer { void SetFocus(string target); } 

要记住几件事:

  1. VM可能提供多个视图实例,因此您的VM可能希望拥有对IFocusContainer实例的引用集合,而不仅仅是一个。
  2. 防御性地编码虚拟机。 您不知道是否有0,1或20个视图正在收听。
  3. SetFocus()的“target”参数应该“松散地”耦合到VM。 您不希望VM关注UI中的确切控件名称。 相反,VM应指明仅为焦点管理定义的名称。 在我的例子中,我创建了一些附加属性,允许我用“焦点名称”“标记”控件。

要实现该接口,您可以:

  1. 在代码隐藏中实现它
  2. 创建一些知道如何附加到DataContext中存在的ViewModel的行为。

在Code Behind上实现它没有任何问题,但是行为方法确实只允许XAML连接,如果这对你很重要的话。

在界面的实现中,您可以使用可视化树来定位控件,或者您可以为一组已知的可聚焦项目编写switch语句。