Подтвердить что ты не робот

Как установить фокус на текстовое поле с помощью MVVM?

Как сфокусировать текстовое поле на ViewModel wpf?

<TextBox Name="PropertySearch"
         Text="{Binding UpdateSourceTrigger=PropertyChanged, 
                        Mode=TwoWay, Path=PropertySearch, 
                        ValidatesOnDataErrors=True}"  
         Width="110" 
         Height="25" 
         Margin="10" />
4b9b3361

Ответ 1

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

Вы можете сделать это с помощью DataTrigger.

Вид:

<Grid Name="LayoutRoot" DataContext="{StaticResource MyViewModelInstance}">
    <Grid.Style>
        <Style>
            <Style.Triggers>
                <DataTrigger Binding="{Binding UserShouldEditValueNow}" Value="True">
                    <Setter Property="FocusManager.FocusedElement" Value="{Binding ElementName=PropertySearch}"/>
                </DataTrigger>
            </Style.Triggers>
        </Style>
    </Grid.Style>
    <TextBox   Name="PropertySearch"   Text="{Binding UpdateSourceTrigger=PropertyChanged, Mode=TwoWay, Path=PropertySearch, ValidatesOnDataErrors=True}" Width="110" Height="25" Margin="10" />
</Grid>

ViewModel:

// When you think the view should set focus on a control
this.UserShouldEditValueNow = true;

Приведенный выше пример упрощается за счет использования только логического свойства ViewModel "UserShouldEditValueNow". Вы можете добавить свойство, подобное этому в ViewModel, или использовать другое свойство выделения, которое указывает это состояние.

Примечание. Итак, почему это делается в MVVM? Одна из причин: предположим, что автор View решил заменить TextBox на ComboBox или даже лучше, предположим, что ваше свойство было целочисленным значением, которое имело как TextBox для просмотра/редактирования номера, так и Slider как еще один способ редактирования одного и того же значения, оба элемента управления связаны с одним и тем же свойством... как бы ViewModel знал, какой элемент управления следует настроить? (когда он не должен даже знать, какие элементы управления или управления связаны с ним в первую очередь). Таким образом, представление может выбрать, какой элемент управления следует сфокусировать, изменив цель привязки ElementName в Setter DataTrigger.

Счастливое кодирование!

Ответ 2

Вопрос, который вы должны задать себе, - "почему мой ViewModel должен знать, какой элемент управления имеет фокус?"

Я бы сказал, что фокус является свойством только для представления; это свойство взаимодействия и не имеет ничего общего с концептуальным состоянием. Это похоже на фоновый цвет элемента управления: зачем вы представляете его в виртуальной машине? Если вам нужно управлять фокусом по-своему, возможно, лучше использовать объект уровня представления для выполнения задания.

Ответ 3

В своем родительском элементе добавьте следующее свойство:

FocusManager.FocusedElement="{Binding ElementName=PropertySearch}" 

Ответ 4

В то время как пуристы могут утверждать, что это исключено из VM, бывают случаи, когда это может иметь смысл сделать это с виртуальной машины.

Мой подход состоял в том, чтобы заставить представление реализовать интерфейс, передать этот интерфейс в ViewModel, а затем позволить методам вызова VM на интерфейсе.

Пример:

public interface IFocusContainer
{
   void SetFocus(string target);
}

Несколько вещей, которые нужно иметь в виду:

  • VM может обслуживать более одного экземпляра представления, поэтому ваша виртуальная машина может захотеть иметь набор ссылок на экземпляры IFocusContainer, а не только один.
  • Обозначьте виртуальную машину. Вы не знаете, прослушиваются ли 0, 1 или 20 просмотров.
  • "Целевой" параметр SetFocus() должен, вероятно, быть "слабо" связан с виртуальной машиной. Вы не хотите, чтобы VM заботилась о точном имени управления в пользовательском интерфейсе. Скорее, виртуальная машина должна указывать имя, которое определяется исключительно для управления фокусом. В моем случае я создал некоторые прикрепленные свойства, которые позволили бы мне "пометить" элементы управления "именами фокуса".

Чтобы реализовать интерфейс, вы можете:

  • Внедрите его в код
  • Создайте некоторые поведения, которые знают, как подключиться к ViewModel, который присутствует в DataContext.

Нет ничего плохого в реализации этого кода в коде, но подход к поведению позволяет использовать только XAML, если это важно для вас.

В реализации интерфейса вы можете использовать визуальное дерево, чтобы найти элемент управления, или вы могли бы просто закодировать оператор switch для известного набора объектов с возможностью фокусировки.