habilitar c# wpf mvvm

c# - habilitar - Pasar al siguiente control al presionar Enter en WPF



onkeypress c# textbox (7)

Quiero pasar al siguiente control cuando presiono la tecla Intro en lugar de la tecla Tab en una aplicación MVVM de WPF. ¿Cómo puedo conseguir esto?


Usando el código subyacente:

Se me ocurrió el siguiente código. Tenga en cuenta que no establece e.Handled. Además, MoveFocus_Next no devuelve si el foco de movimiento fue exitoso, sino más bien si el argumento no es nulo. Puede agregar o eliminar tipos de controles para manejar según sea necesario. El código fue escrito para MainWindow de la aplicación, pero maneja otras ventanas también. También puede adaptar el código para la invocación del evento App_Startup.

using System.Windows; using System.Windows.Controls; using System.Windows.Input; public partial class MainWindow : Window { private bool MoveFocus_Next(UIElement uiElement) { if (uiElement != null) { uiElement.MoveFocus(new TraversalRequest(FocusNavigationDirection.Next)); return true; } return false; } public MainWindow() { InitializeComponent(); } private void Window_Loaded(object sender, RoutedEventArgs e) { EventManager.RegisterClassHandler(typeof(Window), Window.PreviewKeyUpEvent, new KeyEventHandler(Window_PreviewKeyUp)); } private void Window_PreviewKeyUp(object sender, KeyEventArgs e) { if (e.Key == Key.Enter) { IInputElement inputElement = Keyboard.FocusedElement; if (inputElement != null) { System.Windows.Controls.Primitives.TextBoxBase textBoxBase = inputElement as System.Windows.Controls.Primitives.TextBoxBase; if (textBoxBase != null) { if (!textBoxBase.AcceptsReturn) MoveFocus_Next(textBoxBase); return; } if ( MoveFocus_Next(inputElement as ComboBox) || MoveFocus_Next(inputElement as Button) || MoveFocus_Next(inputElement as DatePicker) || MoveFocus_Next(inputElement as CheckBox) || MoveFocus_Next(inputElement as DataGrid) || MoveFocus_Next(inputElement as TabItem) || MoveFocus_Next(inputElement as RadioButton) || MoveFocus_Next(inputElement as ListBox) || MoveFocus_Next(inputElement as ListView) || MoveFocus_Next(inputElement as PasswordBox) || MoveFocus_Next(inputElement as Window) || MoveFocus_Next(inputElement as Page) || MoveFocus_Next(inputElement as Frame) ) return; } } } }


A continuación se muestra una propiedad adjunta que he utilizado para esto.

Primero, uso de ejemplo:

<TextBox Width="100" Text="{Binding Name, Mode=TwoWay}" UI:FocusAdvancement.AdvancesByEnterKey="True" />

(UI es el alias del espacio de nombres para el que he definido lo siguiente).

La propiedad adjunta:

public static class FocusAdvancement { public static bool GetAdvancesByEnterKey(DependencyObject obj) { return (bool)obj.GetValue(AdvancesByEnterKeyProperty); } public static void SetAdvancesByEnterKey(DependencyObject obj, bool value) { obj.SetValue(AdvancesByEnterKeyProperty, value); } public static readonly DependencyProperty AdvancesByEnterKeyProperty = DependencyProperty.RegisterAttached("AdvancesByEnterKey", typeof(bool), typeof(FocusAdvancement), new UIPropertyMetadata(OnAdvancesByEnterKeyPropertyChanged)); static void OnAdvancesByEnterKeyPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { var element = d as UIElement; if(element == null) return; if ((bool)e.NewValue) element.KeyDown += Keydown; else element.KeyDown -= Keydown; } static void Keydown(object sender, KeyEventArgs e) { if(!e.Key.Equals(Key.Enter)) return; var element = sender as UIElement; if(element != null) element.MoveFocus(new TraversalRequest(FocusNavigationDirection.Next)); } }

También dijiste "en lugar de pestaña", así que me pregunto si deseas suprimir la capacidad de usar la pestaña de la forma habitual. Aconsejaría que no lo haga, ya que es un paradigma común y conocido, pero si ese es el caso, puede agregar un controlador PreviewKeyDown en la propiedad adjunta, buscar la tecla de tabulación y establecer Handled = true para el evento args .


Escriba este código en el evento onstartup del archivo de su aplicación

EventManager.RegisterClassHandler(GetType(TextBox), TextBox.KeyDownEvent, New RoutedEventHandler(AddressOf TextBox_KeyDown))

luego defina Sub TextBox_KeyDown como

Private Sub TextBox_KeyDown(ByVal sender As Object, ByVal e As System.Windows.Input.KeyEventArgs) If e.Key = Key.Enter And TryCast(sender, TextBox).Tag <> "1" Then '' Creating a FocusNavigationDirection object and setting it to a '' local field that contains the direction selected. Dim focusDirection As FocusNavigationDirection = FocusNavigationDirection.Next '' MoveFocus takes a TraveralReqest as its argument. Dim request As New TraversalRequest(focusDirection) '' Gets the element with keyboard focus. Dim elementWithFocus As UIElement = TryCast(Keyboard.FocusedElement, UIElement) '' Change keyboard focus. If elementWithFocus IsNot Nothing Then elementWithFocus.MoveFocus(request) End If End If End Sub

He usado la propiedad "tag" del cuadro de texto para saltar el enfoque del movimiento. es decir, si en algún momento no desea pasar al siguiente control, presione la tecla Intro presionada (en el caso del cuadro de texto de líneas múltiples donde se requiere ingresar para crear una nueva línea). Simplemente establezca la propiedad de etiqueta en 1.


Espero esta ayuda: use AttachedProperty http://madprops.org/blog/enter-to-tab-as-an-attached-property/

public class EnterKeyTraversal { public static bool GetIsEnabled(DependencyObject obj) { return (bool)obj.GetValue(IsEnabledProperty); } public static void SetIsEnabled(DependencyObject obj, bool value) { obj.SetValue(IsEnabledProperty, value); } static void ue_PreviewKeyDown(object sender, System.Windows.Input.KeyEventArgs e) { var ue = e.OriginalSource as FrameworkElement; if (e.Key == Key.Enter) { e.Handled = true; ue.MoveFocus(new TraversalRequest(FocusNavigationDirection.Next)); } } private static void ue_Unloaded(object sender, RoutedEventArgs e) { var ue = sender as FrameworkElement; if (ue == null) return; ue.Unloaded -= ue_Unloaded; ue.PreviewKeyDown -= ue_PreviewKeyDown; } public static readonly DependencyProperty IsEnabledProperty = DependencyProperty.RegisterAttached("IsEnabled", typeof(bool), typeof(EnterKeyTraversal), new UIPropertyMetadata(false, IsEnabledChanged)); static void IsEnabledChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { var ue = d as FrameworkElement; if (ue == null) return; if ((bool)e.NewValue) { ue.Unloaded += ue_Unloaded; ue.PreviewKeyDown += ue_PreviewKeyDown; } else { ue.PreviewKeyDown -= ue_PreviewKeyDown; } } }

<StackPanel my:EnterKeyTraversal.IsEnabled="True">


La respuesta de Jay es agradable si solo quieres que funcione en algunos cuadros de texto, pero si quieres que toda tu aplicación funcione de esa manera, definitivamente estoy a favor de la respuesta de makwana.a. Aquí está mi modificación de la respuesta de makwana.a que uso en C #. También incluí soporte para pasar al siguiente control a través de enter si el control activo es una casilla de verificación.

También tenga en cuenta que, en lugar de utilizar la propiedad de etiqueta para indicar si el foco debe moverse o no, utilizo la propiedad AcceptsReturn del cuadro de texto porque su valor predeterminado es falso y solo lo establecerá como verdadero en los cuadros de texto que desee para usar como multi-línea, es decir, que no debe mover el foco en la tecla Enter.

Declare estos controladores de eventos en el vacío de OnStartup de App.xaml

EventManager.RegisterClassHandler(typeof(TextBox), TextBox.KeyDownEvent, new KeyEventHandler(TextBox_KeyDown)); EventManager.RegisterClassHandler(typeof(CheckBox), CheckBox.KeyDownEvent, new KeyEventHandler(CheckBox_KeyDown));

Aquí están el resto de los métodos necesarios para que funcione en toda la aplicación.

void TextBox_KeyDown(object sender, KeyEventArgs e) { if (e.Key == Key.Enter & (sender as TextBox).AcceptsReturn == false) MoveToNextUIElement(e); } void CheckBox_KeyDown(object sender, KeyEventArgs e) { MoveToNextUIElement(e); //Sucessfully moved on and marked key as handled. //Toggle check box since the key was handled and //the checkbox will never receive it. if (e.Handled == true) { CheckBox cb = (CheckBox)sender; cb.IsChecked = !cb.IsChecked; } } void MoveToNextUIElement(KeyEventArgs e) { // Creating a FocusNavigationDirection object and setting it to a // local field that contains the direction selected. FocusNavigationDirection focusDirection = FocusNavigationDirection.Next; // MoveFocus takes a TraveralReqest as its argument. TraversalRequest request = new TraversalRequest(focusDirection); // Gets the element with keyboard focus. UIElement elementWithFocus = Keyboard.FocusedElement as UIElement; // Change keyboard focus. if (elementWithFocus != null) { if (elementWithFocus.MoveFocus(request)) e.Handled = true; } }

Editar

Actualicé el código para marcar la pulsación de tecla como se manejó si el movimiento fue exitoso y también alterné la casilla de verificación desde que se manejó la clave y ya no la alcanzaré.


Lo primero que ocurrió fue agregar un desencadenador a cada elemento que invocará cuando se PreviewKeyDown . También agregue propiedad Dependency y ligue FrameworkElement que no enfocará. Dentro del desencadenador, proporcione la configuración Focus al elemento enlazado.


solución de muestra: usando PreviewKeyDown en el panel de pila. La Vista previa ... es una burbuja para que el evento se pueda manejar en un nivel superior. Es posible que necesite manejar esto de manera diferente para diferentes tipos de elementos, como el botón, parece que debe mantener la tecla Intro y no cambiar el foco en la tecla Intro.

Aquí está el xaml:

<StackPanel PreviewKeyDown="StackPanel_PreviewKeyDown" > <TextBox > Hello </TextBox> <TextBox> World </TextBox> <TextBox> test </TextBox> </StackPanel>

Y aquí está el código detrás:

private void StackPanel_PreviewKeyDown(object sender, KeyEventArgs e) { if (e.Key == Key.Enter) { TextBox s = e.Source as TextBox; if (s != null) { s.MoveFocus(new TraversalRequest( FocusNavigationDirection.Next)); } e.Handled = true; } }

Esto es solo un arenero para prueba de concepto.

Feliz codificación ...