Set focus on TextBox in WPF from view model

c#, mvvm, textbox, wpf, xaml

Solution

Let me answer to your question in three parts.

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 :).

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.

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.

Problem

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}"/> ```

Original source

Related problems