Search code examples
c#wpfxamlmvvmtextbox

Set focus on TextBox in WPF from view model


I have a TextBox and a Button in my view.

Now I am checking a condition upon button click and if the condition turns out to be false, displaying the message to the user, and then I have to set the cursor to the TextBox control.

if (companyref == null)
{
    var cs = new Lipper.Nelson.AdminClient.Main.Views.ContactPanels.CompanyAssociation(); 

    MessageBox.Show("Company does not exist.", "Error", MessageBoxButton.OK,
                    MessageBoxImage.Exclamation);

    cs.txtCompanyID.Focusable = true;

    System.Windows.Input.Keyboard.Focus(cs.txtCompanyID);
}

The above code is in the ViewModel.

The CompanyAssociation is the view name.

But the cursor is not getting set in the TextBox.

The xaml is:

<igEditors:XamTextEditor Name="txtCompanyID" 
                         KeyDown="xamTextEditorAllowOnlyNumeric_KeyDown"
                         ValueChanged="txtCompanyID_ValueChanged"
                         Text="{Binding Company.CompanyId,
                                        Mode=TwoWay,
                                        UpdateSourceTrigger=PropertyChanged}"
                         Width="{Binding ActualWidth, ElementName=border}"
                         Grid.Column="1" Grid.Row="0"
                         VerticalAlignment="Top"
                         HorizontalAlignment="Stretch"
                         Margin="0,5,0,0"
                         IsEnabled="{Binding Path=IsEditable}"/>

<Button Template="{StaticResource buttonTemp1}"
        Command="{Binding ContactCommand}"
        CommandParameter="searchCompany"
        Content="Search"
        Width="80"
        Grid.Row="0" Grid.Column="2"
        VerticalAlignment="Top"
        Margin="0"
        HorizontalAlignment="Left"
        IsEnabled="{Binding Path=IsEditable}"/>

Solution

  • Let me answer to your question in three parts.

    1. I'm wondering what is "cs.txtCompanyID" in your example? Is it a TextBox control? If yes, then you are on a wrong way. Generally speaking it's not a good idea to have any reference to UI in your ViewModel. You can ask "Why?" but this is another question to post on Stackoverflow :).

    2. The best way to track down issues with Focus is... debugging .Net source code. No kidding. It saved me a lot of time many times. To enable .net source code debugging refer to Shawn Bruke's blog.

    3. Finally, general approach that I use to set focus from ViewModel is Attached Properties. I wrote very simple attached property, which can be set on any UIElement. And it can be bound to ViewModel's property "IsFocused" for example. Here it is:

       public static class FocusExtension
       {
           public static bool GetIsFocused(DependencyObject obj)
           {
               return (bool) obj.GetValue(IsFocusedProperty);
           }
      
           public static void SetIsFocused(DependencyObject obj, bool value)
           {
               obj.SetValue(IsFocusedProperty, value);
           }
      
           public static readonly DependencyProperty IsFocusedProperty =
               DependencyProperty.RegisterAttached(
                   "IsFocused", typeof (bool), typeof (FocusExtension),
                   new UIPropertyMetadata(false, OnIsFocusedPropertyChanged));
      
           private static void OnIsFocusedPropertyChanged(
               DependencyObject d, 
               DependencyPropertyChangedEventArgs e)
           {
               var uie = (UIElement) d;
               if ((bool) e.NewValue)
               {
                   uie.Focus(); // Don't care about false values.
               }
           }
       }
      

      Now in your View (in XAML) you can bind this property to your ViewModel:

       <TextBox local:FocusExtension.IsFocused="{Binding IsUserNameFocused}" />
      

    If this answer doesn't help, refer to the answer #2.