JoacimWall
JoacimWall

Reputation: 41

Set focus to textbox in UWP from ViewModel

Сan anyone tell me how to set focus from ViewModel to TextBox in UWP Mobile app. My senario is

  1. User scan a barcode that says: manual input
  2. My ViewNodel change binding on TextBox.Visibility from Collapsed to Visible
  3. I want to trigger SetFocus or Tapped event so the marker is inside the TextBox and the keyboard is shown.

Upvotes: 0

Views: 1182

Answers (1)

Yves
Yves

Reputation: 792

Although a ViewModel is not really suited for this, the best way to set a focus from a ViewModel is by creating a dependency property for it, and then binding to it.

public static class FocusExtension
{
    public static bool GetIsFocused(Control obj)
    {
        return (bool)obj.GetValue(IsFocusedProperty);
    }

    public static void SetIsFocused(Control obj, bool value)
    {
        obj.SetValue(IsFocusedProperty, value);
    }

    public static readonly DependencyProperty IsFocusedProperty = DependencyProperty.RegisterAttached(
        "IsFocused", typeof(bool), typeof(FocusExtension),
        new PropertyMetadata(false, OnIsFocusedPropertyChanged));

    private static void OnIsFocusedPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        var control = (Control)d;

        if ((bool)e.NewValue != (bool)e.OldValue)
        {
            if ((bool)e.NewValue)
            {
                control.Focus(FocusState.Programmatic);
                control.LostFocus += Control_LostFocus;
            }
            else
            {
                control.GotFocus += Control_GotFocus;
            }
        }
    }

    private static void Control_GotFocus(object sender, RoutedEventArgs e)
    {
        var control = (Control)sender;
        control.SetValue(IsFocusedProperty, true);
        control.GotFocus -= Control_GotFocus;
    }

    private static void Control_LostFocus(object sender, RoutedEventArgs e)
    {
        var control = (Control)sender;
        control.SetValue(IsFocusedProperty, false);
        control.LostFocus -= Control_LostFocus;
    }
}

You can bind to it like this (two way binding is recommended, as the focus will ony be set once because the property would not be set back to false after losing focus)

<TextBox extensions:FocusExtension.IsFocused="{Binding IsTextBoxFocused, Mode=TwoWay}"/>

Upvotes: 3

Related Questions