2011-09-09 9 views
7

Mi configuración es como se describe a continuación:de datos no actualiza la propiedad al pulsar Intro en un cuadro de diálogo con un botón predeterminado

  • WPF 4 aplicación marco
  • MVVM Lite
  • Un "Agregar elemento "ventana se muestra en la parte superior de la ventana principal en modo de diálogo (usando view.ShowDialog();)
  • El cuadro de diálogo tiene una serie de campos de entrada y el botón" Guardar "que tiene la propiedad IsDefault establecida en True
  • El botón "Guardar" está a mano conducido usando una unión a un comando
  • de datos se define la unión entre los campos de entrada en XAML de vista y las propiedades correspondientes en el modelo de vista (de una manera, para la interfaz de usuario para actualizar el modelo de vista, con Mode = OneWayToSource)

El problema es que cuando presiono Enter en el teclado, el valor que proporcioné en el último campo de entrada no se envía a la propiedad subyacente de ViewModel.

Sospecho que esto tiene algo que ver con el hecho de que el campo de entrada no ha perdido el foco antes de que se cierre la ventana (y por lo tanto todas las vinculaciones se "disuelven"). Para comparar, si haga clic en el botón "Guardar" (en lugar de dejar que su Click sea manejado por la ventana en Entrar), el valor es actualizado en la propiedad. Además, si agrego (¡horror! Horror!) Un controlador de eventos al evento Click del botón, y llamo a button.Focus() en código subyacente, ¡todo funciona!

¿Cuál puede ser el remedio?

Yo, obviamente, no quiero manejar cualquier ventana de eventos de cierre, y "manual" Recuperar los valores que faltan ... esto violaría el concepto MVVM :-(

mejor sugerencia?

Gracias, Alex

+0

Me he encontrado con este mismo comportamiento en varios otros idiomas, especialmente Delphi (supongo que Hejlsberg consideró que esta característica no era una falla, si también era responsable de WPF). La opción PropertyChanged tiene problemas si se vincula a un número, porque intentará validar "3". mientras escribes Pi y haces una excepción. No me importa el botón. Opción de enfoque() ya que funcionará con todos los controles y también a prueba futura del diálogo. –

Respuesta

12

De forma predeterminada, TextBox solo notifica a su fuente que su valor ha cambiado una vez que pierde el foco. Puede cambiar eso en su enlace configurando UpdateSourceTrigger=PropertyChanged. Esto hará que el TextBox envíe una notificación de actualización a su fuente. El texto se cambia en lugar de solo cuando pierde el foco.

Si no desea enviar una notificación de actualización cada vez que se presiona una tecla, puede crear un AttachedProperty para actualizar la fuente si se presiona la tecla Intro.

Aquí está la AttachedProperty que utilizo para situaciones como esta:

// When set to True, Enter Key will update Source 
#region EnterUpdatesTextSource DependencyProperty 

// Property to determine if the Enter key should update the source. Default is False 
public static readonly DependencyProperty EnterUpdatesTextSourceProperty = 
    DependencyProperty.RegisterAttached("EnterUpdatesTextSource", typeof (bool), 
             typeof (TextBoxHelper), 
             new PropertyMetadata(false, EnterUpdatesTextSourcePropertyChanged)); 

// Get 
public static bool GetEnterUpdatesTextSource(DependencyObject obj) 
{ 
    return (bool) obj.GetValue(EnterUpdatesTextSourceProperty); 
} 

// Set 
public static void SetEnterUpdatesTextSource(DependencyObject obj, bool value) 
{ 
    obj.SetValue(EnterUpdatesTextSourceProperty, value); 
} 

// Changed Event - Attach PreviewKeyDown handler 
private static void EnterUpdatesTextSourcePropertyChanged(DependencyObject obj, 
                  DependencyPropertyChangedEventArgs e) 
{ 
    var sender = obj as UIElement; 
    if (obj != null) 
    { 
     if ((bool) e.NewValue) 
     { 
      sender.PreviewKeyDown += OnPreviewKeyDownUpdateSourceIfEnter; 
     } 
     else 
     { 
      sender.PreviewKeyDown -= OnPreviewKeyDownUpdateSourceIfEnter; 
     } 
    } 
} 

// If key being pressed is the Enter key, and EnterUpdatesTextSource is set to true, then update source for Text property 
private static void OnPreviewKeyDownUpdateSourceIfEnter(object sender, KeyEventArgs e) 
{ 
    if (e.Key == Key.Enter) 
    { 
     if (GetEnterUpdatesTextSource((DependencyObject) sender)) 
     { 
      var obj = sender as UIElement; 
      BindingExpression textBinding = BindingOperations.GetBindingExpression(
       obj, TextBox.TextProperty); 

      if (textBinding != null) 
       textBinding.UpdateSource(); 
     } 
    } 
} 

#endregion //EnterUpdatesTextSource DependencyProperty 
3

Prueba esto.

{Binding propiedad, UpdateSourceTrigger = PropertyChanged, Modo = OneWayToSource}

-3

Es simplemente un error de WPF. (Diseño o implementación, no sé). La actualización de TextBox en foco perdido es el comportamiento esperado en la mayoría de los casos y también el botón predeterminado debe funcionar en los cuadros de diálogo.

Para la solución, creo que es una dirección incorrecta para atemperar con el TextBox. Una mejor solución es forzar el enfoque al botón predeterminado.

0

Un simple truco es alejar el foco del control, p. al botón en sí. Esto se puede hacer clic en el controlador del botón, ya que será ejecutado antes de que el comando de cota:

public MyView() 
    { 
     InitializeComponent(); 

     _button.Click += delegate 
     { 
      _button.Focus(); 
     }; 
    } 

Si no les gusta código detrás en su opinión, también se puede hacer esto en un comportamiento que agregue a su botón.

Cuestiones relacionadas