MVVM Focus To Textbox

时间:2010-05-14 14:42:00

标签: wpf mvvm textbox

如何在不指定TextBox的名称的情况下将焦点设置为TextBox?目前我正在做以下事情

<Window FocusManager.FocusedElement="{Binding ElementName=Username}">
    <Grid>
        <TextBox Text="{Binding Username}" Name="Username" />            
    </Grid>
</Window>

如果没有为TextBox指定名称,有没有办法做到这一点。我相信具有Name元素的MVVM通常意味着糟糕的设计?

6 个答案:

答案 0 :(得分:21)

  

我相信MVVM中有一个Name元素通常意味着糟糕的设计?

不,不是。

MVVM模式不是要从代码隐藏文件中删除所有代码。

关注问题的分离和提高可测试性。 查看焦点处理等相关代码应保留在View的代码隐藏文件中。但是在View的代码隐藏文件中看到应用程序逻辑或数据库连接管理会很糟糕。

可以在 WPF Application Framework (WAF) 项目中找到MVVM示例,其中包含代码隐藏文件中的代码而不违反MVVM模式。

答案 1 :(得分:6)

简单的方法是在UserControl_Load事件中设置焦点

        this.txtBox.Focus();
        txtBox.Focusable = true;
        Keyboard.Focus(txtBox);

MVVM并不意味着您无法将代码放在代码隐藏文件中。 事实上,不要让任何模式限制你找到最好的编码方式。

答案 2 :(得分:3)

我在a similar problem的回答中记录了一种“纯MVVM”方式。该解决方案涉及使用附加属性和框架将接口命令从ViewModel传递回View。

答案 3 :(得分:3)

应尽可能避免代码落后,甚至在视图中更多。我有同样的问题,出于简单的目的,最好的答案就是这个,因为它只修改了视图:

WPF MVVM Default Focus on Textbox and selectAll

如果您希望在与其他UserControl元素交互时再次设置焦点,则可以解决这个问题:

Set focus on textbox in WPF from view model (C#)

我失去了3天来解决这个问题,我希望这会有所帮助。

答案 4 :(得分:0)

实际上,我发现布尔附加属性解决方案有点脏和笨拙的方式,你必须找到一个扭曲,以确保下一组视图模型属性将真正引发附加属性更改事件。

一个简单而优雅的解决方案是将您的行为绑定在属性类型上,您可以确保下一个值始终与前一个值不同,从而确保您的附加属性更改事件每次都会引发。

最简单的类型是int。然后解决方案通常是:

的组合

行为:

public static class TextBoxFocusBehavior
{
    public static int GetKeepFocus(DependencyObject obj)
    {
        return (int)obj.GetValue(KeepFocusProperty);
    }

    public static void SetKeepFocus(DependencyObject obj, int value)
    {
        obj.SetValue(KeepFocusProperty, value);
    }

    // Using a DependencyProperty as the backing store for KeepFocus.  This enables animation, styling, binding, etc...
    public static readonly DependencyProperty KeepFocusProperty =
        DependencyProperty.RegisterAttached("KeepFocus", typeof(int), typeof(TextBoxFocusBehavior), new UIPropertyMetadata(0, OnKeepFocusChanged));

    private static void OnKeepFocusChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        TextBox t = d as TextBox;
        if (t != null)
        {
            t.Focus();
        }
    }
}

视图模型属性:

    public int InputFocus
    {
        get { return _inputFocus; }
        private set
        {
            _inputFocus = value;
            Notify(Npcea.InputFocus);
        }
    }

使用附加行为:

 <TextBox  v:TextBoxFocusBehavior.KeepFocus="{Binding InputFocus}"/>

最后在VM中使用该属性:

    public void YouMethod()
    {
        //some code logic
        InputFocus++;//<= the textbox focus
    }

一些非常糟糕的精神可能会说这个逻辑与int32大小限制有关。好吧......我现在就选择忽略它们; - )

答案 5 :(得分:0)

  

我相信具有Name元素的MVVM通常意味着糟糕的设计?

     

不,不是。

据微软MVP称,不仅命名控件是WPF的不良做法,它对性能的影响相当大。只是想传递一些智慧的话语

我同意Sean Du关于不让任何模式完全限制你的观点,我认为应该尽可能避免性能受损。