12

How would I set focus to a TextBox without specifying the name for that TextBox? At the moment I am doing the following

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

Is there any way of doing this without specifying a Name for the TextBox. As I believe in MVVM having a Name element usually means bad design?

Dave Clemmer
  • 3,741
  • 12
  • 49
  • 72
Michal Ciechan
  • 13,492
  • 11
  • 76
  • 118
  • I don't think having a name for an element is bad design per se, but giving an element a name just so that you can refer to it in code-behind should be avoided. I don't see anything wrong with your view above. – lesscode May 14 '10 at 14:50
  • Consider if you want to use triggers to do anything special in the view (animation and other state changes) - name is critical for those. – Gusdor Jul 26 '11 at 12:36

6 Answers6

28

As I believe in MVVM having a Name element usually means bad design?

No, it’s not.

The MVVM pattern is not about eliminating all the code from code-behind files.

It is about separating of concerns and increasing the testability. View related code like focus handling should remain in the code-behind file of the View. But it would be bad to see application logic or database connection management in the code-behind file of the View.

MVVM examples with code in the code-behind files without violating the MVVM pattern can be found at the WPF Application Framework (WAF) project.

jbe
  • 6,976
  • 1
  • 43
  • 34
8

The simple way is to set focus in UserControl_Load event

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

MVVM doesn't mean you can not put code in the code behind file. In fact, Do not let any pattern restrict you to find the best way of coding.

Sean Du
  • 81
  • 1
  • 1
4

I have documented a "pure MVVM" way to do this in my answer to a similar problem. The solution involves using Attached Properties and a framework for passing interface commands from the ViewModel back to the View.

Community
  • 1
  • 1
Joseph Sturtevant
  • 13,194
  • 12
  • 76
  • 90
  • http://geekswithblogs.net/HouseOfBilz/archive/2009/08/27/adventures-in-mvvm-ndash-binding-commands-to-any-event.aspx – Agies May 21 '10 at 02:03
3

Code behind should be avoided when possible, even more when it is in the view. I had the same problem and for simple purposes the best answer is this one as it only modifies the view:

WPF MVVM Default Focus on Textbox and selectAll

If you are looking to set again focus as you interact with other UserControl elements, this will do the trick:

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

I lost 3 days figuring this out, I hope this can help.

Community
  • 1
  • 1
C3PO
  • 147
  • 4
  • 15
0

Actually, I found the boolean attached property solution a bit dirty and clumsy in the way that you have to find a twist in order to be sure that the next set of your view model property will really raise the attached property changed event.

A simple and more elegant solution is to bind your behavior on property type for which you can be sure that the next value will always be different from the previous one and thus be sure that your attached property changed event will raise every times.

The most simple type that comes into mind is the int. The solution is then the usual combination of :

The behavior:

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();
        }
    }
}

The view model property:

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

The use of the attached behavior:

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

And finaly the use of the property in the VM:

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

Some REALLY bad minded spirits might say that this logic is bound to the int32 size limitation. Well... I will just choose to ignore them right now ;-)

McGuireV10
  • 9,572
  • 5
  • 48
  • 64
Bruno
  • 1,944
  • 13
  • 22
0

As I believe in MVVM having a Name element usually means bad design?

No, it’s not.

According to Microsoft MVP's not only is naming controls is WPF bad practice, it is a quite substantial hit on performance. Just wanted to pass along some words of wisdom

I agree with Sean Du about not letting any pattern totally restrict you, I think performance hit should be avoided whenever possible.

Community
  • 1
  • 1
Lane
  • 9
  • 1