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

Поле фокусировки WPF MVVM при загрузке

У меня есть представление, у которого есть один TextBox и пара Button под ним. Когда окно загружается, я хочу, чтобы TextBox имел фокус.

Если я не использовал MVVM, я бы просто вызвал TextBox.Focus() в событии Loaded. Однако мой ViewModel не знает о моем представлении, так как я могу выполнить это, не введя код в кодовое имя моего представления?

EDIT: После прочтения ответов я решил поместить этот код в представление xaml

<DockPanel FocusManager.FocusedElement="{Binding ElementName=MessageTextBox}">    
    <TextBox Name="MessageTextBox" Text="{Binding Message}"/>
</DockPanel>

Если бы это было что-то другое, кроме начального фокуса страницы, я бы, вероятно, рекомендовал ответ Джона Галлоуэя, поскольку он может управляться из ViewModel.

4b9b3361

Ответ 1

Если вам становится лучше (мне становится легче), вы можете сделать это в Xaml, используя прикрепленное свойство:

http://msdn.microsoft.com/en-us/library/system.windows.input.focusmanager.focusedelement.aspx

Все, что вы можете сделать в коде, вы можете сделать в Xaml, если знаете трюки. К счастью, вам не пришлось реализовывать этот трюк - MS сделала это для вас.

Ответ 2

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

Ответ 3

  • У вас есть свойство в вашей ViewModel, которое указывает, какой элемент находится в данный момент.
  • Используйте FocusManager для привязки к этому свойству.

    <Window FocusManager.FocusedElement="{Binding ElementName=ViewModel.FocusedItem}"/>
    

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

Ответ 4

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

Это означает, что логика пользовательского интерфейса остается в представлении - TextBox.Focus(), на мой взгляд, является подходящим способом сделать это.

Ответ 5

Я считаю, что управление с фокусом будет очень "визуальным", поэтому не было бы проблем с тем, что он находится в коде.

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

Ответ 6

После "WPF Initial Focus Nightmare" и основанного на некоторых ответах на стеке, для меня было лучшим решением.

Сначала добавьте App.xaml OnStartup() следующее:

EventManager.RegisterClassHandler(typeof(Window), Window.LoadedEvent,
          new RoutedEventHandler(WindowLoaded));

Затем добавьте событие WindowLoaded также в App.xaml:

void WindowLoaded(object sender, RoutedEventArgs e)
    {
        var window = e.Source as Window;
        System.Threading.Thread.Sleep(100);
        window.Dispatcher.Invoke(
        new Action(() =>
        {
            window.MoveFocus(new TraversalRequest(FocusNavigationDirection.First));

        }));
    }

Проблема с потоками должна использоваться, поскольку первоначальный фокус WPF в основном не работает из-за некоторых условий рамочной гонки.

Я нашел следующее решение наилучшим, поскольку оно используется глобально для всего приложения.

Надеюсь, что это поможет...

Оран