Установить фокус на текстовое поле в UWP из ViewModel

Кто-нибудь может подсказать, как установить фокус с ViewModel на TextBox в мобильном приложении UWP. Мой Сенарио

  1. Пользователь сканирует штрих-код, который говорит: ручной ввод
  2. Привязка моего ViewNodel к TextBox.Visibility изменена с Collapsed на Visible
  3. Я хочу вызвать событие SetFocus или Tapped, чтобы маркер находился внутри TextBox и отображалась клавиатура.

person JoacimWall    schedule 31.01.2017    source источник
comment
Вы не пробовали настроить фокус? небольшой образец   -  person Romasz    schedule 31.01.2017
comment
Не пытайтесь сделать это только из ViewModel. Вам нужна некоторая логика, ориентированная на представление, и код программной части — подходящее место для этого. Привяжите какой-нибудь программный код к логическому свойству или событию на виртуальной машине.   -  person Henk Holterman    schedule 31.01.2017
comment
Хенк Холтман, у вас есть пример? из кода, стоящего за свойством, чтобы установить foucs?   -  person JoacimWall    schedule 31.01.2017
comment
Нет, но вы смотрели на небольшой образец от @Romasz?   -  person Henk Holterman    schedule 31.01.2017
comment
да, вы можете использовать метод Control.Focus. поэтому из кода xaml, основанного на вызове ситуации, подобном этому yourControlName.Focus(FocusState.Programmatic);   -  person Kiran Paul    schedule 31.01.2017
comment
Я считаю, что в рамках этого есть поведение   -  person mvermef    schedule 01.02.2017
comment
Спасибо @Kiran Paul, это решило эту проблему. Я использовал prism.event, чтобы отправить сообщение из модели представления в код позади, чтобы установить фокус.   -  person JoacimWall    schedule 01.02.2017
comment
Обмен сообщениями в порядке, но излишне сложен. Код программной части может (может) обращаться к виртуальной машине напрямую, например, чтобы подписаться на событие.   -  person Henk Holterman    schedule 01.02.2017


Ответы (1)


Хотя ViewModel на самом деле не подходит для этого, лучший способ установить фокус из ViewModel — создать для него свойство зависимости, а затем привязать его.

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

Вы можете привязаться к нему следующим образом (рекомендуется двусторонняя привязка, так как фокус будет установлен только один раз, потому что свойство не будет установлено обратно в false после потери фокуса)

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