Поле фокусировки 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.
Ответы
Ответ 1
Если вам становится лучше (мне становится легче), вы можете сделать это в Xaml, используя прикрепленное свойство:
http://msdn.microsoft.com/en-us/library/system.windows.input.focusmanager.focusedelement.aspx
Все, что вы можете сделать в коде, вы можете сделать в Xaml, если знаете трюки. К счастью, вам не пришлось реализовывать этот трюк - MS сделала это для вас.
Ответ 2
В этом случае я думаю, что это хорошо, чтобы поместить код в представление. Настройка фокуса на элемент управления влияет на поведение пользовательского интерфейса, а не на логику приложения и, следовательно, несет ответственность за представление.
Ответ 3
Ваш 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 в основном не работает из-за некоторых условий рамочной гонки.
Я нашел следующее решение наилучшим, поскольку оно используется глобально для всего приложения.
Надеюсь, что это поможет...
Оран