如何使用MVVM对文本框设置焦点
本文关键字:设置 焦点 文本 何使用 MVVM | 更新日期: 2023-09-27 18:02:21
如何从ViewModel wpf聚焦文本框?
<TextBox Name="PropertySearch"
Text="{Binding UpdateSourceTrigger=PropertyChanged,
Mode=TwoWay, Path=PropertySearch,
ValidatesOnDataErrors=True}"
Width="110"
Height="25"
Margin="10" />
你可以通过添加一个属性到你的ViewModel(或使用一个现有的属性),这表明SetFocus应该发生,但视图应该负责实际设置焦点,因为这纯粹是视图相关的。
你可以用一个datattrigger来做这个。
视图:
<Grid Name="LayoutRoot" DataContext="{StaticResource MyViewModelInstance}">
<Grid.Style>
<Style>
<Style.Triggers>
<DataTrigger Binding="{Binding UserShouldEditValueNow}" Value="True">
<Setter Property="FocusManager.FocusedElement" Value="{Binding ElementName=PropertySearch}"/>
</DataTrigger>
</Style.Triggers>
</Style>
</Grid.Style>
<TextBox Name="PropertySearch" Text="{Binding UpdateSourceTrigger=PropertyChanged, Mode=TwoWay, Path=PropertySearch, ValidatesOnDataErrors=True}" Width="110" Height="25" Margin="10" />
</Grid>
ViewModel:
// When you think the view should set focus on a control
this.UserShouldEditValueNow = true;
上面的例子通过使用一个布尔ViewModel属性"UserShouldEditValueNow"来简化。你可以像这样添加一个属性到你的ViewModel,或者使用其他一些现有的属性来指示这个状态。
注意:那么为什么在MVVM中这样做呢?一个原因是,假设视图作者决定用ComboBox代替TextBox,或者更好,假设你的属性是一个整数值,有一个TextBox来查看/编辑数字和 Slider作为编辑相同值的另一种方式,两个控件绑定到相同的属性…ViewModel如何知道要将焦点设置在哪个控件上?(当它甚至不应该知道一个或多个控件被绑定到它的时候)这样,视图可以通过改变DataTrigger Setter中的ElementName绑定目标来选择关注哪个控件。
编码快乐!
你应该问自己的问题是"为什么我的ViewModel需要知道哪个控件有焦点?"
我认为焦点是一个仅视图属性;这是一个相互作用的性质,与概念状态无关。这类似于控件的背景颜色:为什么要在VM中表示它?如果您需要以自定义方式管理焦点,最好使用视图级对象来完成这项工作。
在父控件中添加以下属性:
FocusManager.FocusedElement="{Binding ElementName=PropertySearch}"
虽然纯粹主义者可能会争论将此从VM中移除,但在某些情况下,从VM中这样做可能是有意义的。
我的方法是让视图实现一个接口,将该接口传递给ViewModel,然后让VM调用接口上的方法。
的例子:
public interface IFocusContainer
{
void SetFocus(string target);
}
要记住的几件事:
- 一个VM可能服务于一个视图的多个实例,所以你的VM可能想要有一个引用IFocusContainer实例的集合,而不仅仅是一个。
- 对虚拟机进行防御性编码。你不知道有0、1还是20个视图在监听。
- SetFocus()的"target"参数应该"松散"耦合到VM。您不希望VM关心UI中确切的控件名称。相反,VM应该指示一个仅为焦点管理而定义的名称。在我的例子中,我创建了一些附加属性,允许我用"焦点名称"标记"控件。
要实现接口,您可以:
- 在后台代码 中实现
- 创建一些知道如何附加到DataContext中存在的ViewModel的行为
在后台代码上实现它没有什么错,但是如果对您很重要的话,行为方法确实允许仅XAML连接。
在接口的实现中,您可以使用可视化树来定位控件,或者您可以为一组已知的可聚焦项编写一个switch语句。