Pregunta Campo de enfoque de WPF MVVM en carga


Tengo una vista que tiene un solo TextBox y una pareja Buttons debajo de él. Cuando la ventana se carga, quiero eso TextBox tener foco

Si no estuviera usando MVVM, solo llamaría TextBox.Focus() en el evento Loaded. Sin embargo, mi ViewModel no sabe acerca de mi vista, ¿cómo puedo lograr esto sin poner código en el código detrás de mi vista?

EDITAR: Después de leer las respuestas, decidí poner este código en la vista xaml

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

Si esto fuera otra cosa que el enfoque inicial de la página, probablemente recomendaría la respuesta de Jon Galloway, ya que se puede controlar desde ViewModel.


48
2017-07-24 15:32


origen


Respuestas:


Si te hace sentir mejor (me hace sentir mejor) puedes hacerlo en Xaml usando una propiedad adjunta:

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

Cualquier cosa que puedas hacer en código subyacente puedes hacerlo en Xaml si conoces los trucos. Afortunadamente, no tienes que implementar este truco, MS lo hizo por ti.


48
2017-07-24 15:40



En este caso, creo que está bien poner el código en la vista. Establecer el foco en un control afecta el comportamiento de la interfaz de usuario en lugar de la lógica de la aplicación y, por lo tanto, es responsabilidad de la vista.


14
2017-07-24 15:38



  1. Tener una propiedad en su ViewModel que indique cuál es el elemento actualmente enfocado.
  2. Use el FocusManager para enlazar a esa propiedad.

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

Su ViewModel es un traductor que existe únicamente para proporcionar información a la Vista, por lo que puede agregar cualquier información a la VM que la Vista necesite para funcionar.


10
2017-07-24 15:40



En realidad, ¿no se enfoca una preocupación UI? MVVM trata de separar las preocupaciones: lo que pertenece al modelo está en el modelo, lo que pertenece a la vista está a la vista, y lo que une el modelo y la vista juntos está en ViewModel (esta es, por supuesto, una descripción simplificada).

Esto significa que la lógica de UI permanece en View - TextBox.Focus () es, en mi opinión, una forma adecuada de hacer que esto suceda.


8
2017-07-24 15:40



Considero que el control con foco es mucho más que "solo visual", por lo que no tendría ningún problema con que ese código esté detrás.

La idea de una máquina virtual es alejar la lógica de la vista y proporcionar una versión amigable de enlace de datos de su modelo para que la vista se una. Esto no significa necesariamente que todas El código debe vivir en la máquina virtual, solo el código lógico y todo lo que no esté directamente relacionado con la interfaz de usuario.


4
2017-07-24 15:40



Después de tener un 'WPF Initial Focus Nightmare' y basado en algunas respuestas en la pila, lo siguiente me resultó ser la mejor solución.

Primero, agregue su App.xaml OnStartup () los siguientes:

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

A continuación, agregue el evento 'WindowLoaded' también en 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));

        }));
    }

El problema de enhebrado debe ser utilizado ya que el enfoque inicial de WPF falla principalmente debido a algunas condiciones de carrera de infraestructura.

Encontré la siguiente solución mejor, ya que se usa globalmente para toda la aplicación.

Espero eso ayude...

Orán


2
2018-01-24 17:39