WPF MVVM Focus Field on Load

33,799

Solution 1

If it makes you feel better (it makes me feel better) you can do this in Xaml using an attached property:

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

Anything you can do in codebehind you can do in Xaml if you know the tricks. Fortunately, you didn't have to implement this trick - MS did it for you.

Solution 2

In this case I think that it is fine to put the code into the view. Setting focus to a control affects the behaviour of the user interface rather than logic of the application and therefore is the responsibility of the view.

Solution 3

Actually, isn't focus a UI concern? MVVM is about separating concerns - what belongs to model is in model, what belongs to view is in view, and what bind model and view together is in ViewModel (this is of course oversimplified description).

This means, that UI logic remains in View - TextBox.Focus() is, in my opinion, appropriate way to make this happen.

Solution 4

  1. Have a property in your ViewModel which indicates which is the currently focused element.
  2. Use the FocusManager to bind to that property.

    <Window FocusManager.FocusedElement="{Binding ElementName=ViewModel.FocusedItem}"/>
    

Your ViewModel is a translator which exists solely to provide information to the View, so you can add whatever information to the VM that the View needs to function.

Solution 5

I'd consider the control with focus to be very much "visual only", so wouldn't have any problem with that being in code behind.

The idea of a VM is to move logic away from the View, and provide a databinding friendly version of your model for the view to bind to. This doesn't necessarily mean that all code should live in the VM, just the logic code and anything that isn't directly tied to the UI.

Share:
33,799
Shaun Bowe
Author by

Shaun Bowe

.Net Developer in the Milwaukee area

Updated on July 09, 2022

Comments

  • Shaun Bowe
    Shaun Bowe almost 2 years

    I have a View that has a single TextBox and a couple Buttons below it. When the window loads I want that TextBox to have focus.

    If I was not using MVVM I would just call TextBox.Focus() in the Loaded event. However my ViewModel does not know about my view so how can I accomplish this without putting code into the codebehind of my view?

    EDIT: After reading the answers I decided to put this code in the view xaml

    <DockPanel FocusManager.FocusedElement="{Binding ElementName=MessageTextBox}">    
        <TextBox Name="MessageTextBox" Text="{Binding Message}"/>
    </DockPanel>
    

    If this were anything other than initial page focus I would probably recommend Jon Galloway's answer since it can be controlled from the ViewModel.

  • Shaun Bowe
    Shaun Bowe almost 15 years
    That is kind of what I thought. I just feel a little dirty every time I think about adding code to the view. In this case it seems to make sense though.
  • Martin Harris
    Martin Harris almost 15 years
    I think that once I changed my MVVM philosophy from "no code behind" to "minimum and pertinent code behind" my life became a lot easier. I hadn't heard of the attached property that Anderson Imes has mentioned, and it sounds like a good solution to the bad taste that code behind gives you, but don't be afraid to put legitimate, non-logic code in the UI.
  • Shaun Bowe
    Shaun Bowe almost 15 years
    That is exactly what I was looking for. I think this code does belong in the view and for some reason I like it better in the xaml than the code behind.
  • Anderson Imes
    Anderson Imes almost 15 years
    Galloway's suggestion allows you to control focus from the ViewModel... you might take a closer look at that as well.
  • Shaun Bowe
    Shaun Bowe almost 15 years
    After reading some of the other answers I am not sure that code belongs in the ViewModel. It seems to be tied directly to the view. If I had a more complex page that was actually moving focus based on other events that would probably make sense. That said it is still a nice trick to have.
  • Gishu
    Gishu about 14 years
    IMHO, the VM should have no information about control names or types in the actual view implementation. Instead I'd let the view listen for a property change notification from the VM and then let it handle it. e.g. ActivateNameField goes to true.. the View finds the relevant control and sets the focus to it.
  • user1055201
    user1055201 almost 14 years
    I agree that the VM must have a role in the process when business logic is involved. Once the design calls for "when they select this checkbox and they are an admin then set focus to the OverrideReason textbox" then the logic belong in the VM. The trick is getting the View to respect the property change.
  • Josh G
    Josh G over 13 years
    I'm so in agreement with you. I don't think it makes sense to get religious about eliminating code from the view. The important thing is that code in the view should be very UI related. Code in the VM contains the state and other logic pertaining to the model. A litmus test is whether the code could/should be tested. Code in the view can NOT be tested.
  • Matt Gregory
    Matt Gregory about 4 years
    How does this work? If you set ElementName=ViewModel.FocusedItem, it's going to look for an element named literally "ViewModel.FocusedItem", isn't it? I'm trying to use my ViewModel typed variable that I've set in my codebehind (and assigned to the DataContext of my page), but the ElementName property can't see it.