2010-05-12 14 views
12

La primera vez que visualizo mi pantalla para el usuario, prefiero no mostrar todos los mensajes de validación para los campos obligatorios y antes de que el usuario haya tenido la oportunidad de completar cualquiera de los campos del formulario. Establecí UpdateSourceTrigger en mis enlaces en LostFocus, pero los errores aún se muestran la primera vez que se muestra el control. ¿Hay alguna forma de evitar esto?¿Cómo puedo obtener que WPF NO muestre errores de validación al mostrar el control inicial?

XAML:

<TextBox Text="{Binding Path=OpeningOdometer, ValidatesOnDataErrors=True, UpdateSourceTrigger=LostFocus}" /> 

modelo de vista:

[Required(ErrorMessage = "Please enter the opening odometer.")] 
[Range(0, Double.MaxValue, ErrorMessage = "Opening Odometer must be a positive number")]   
public string OpeningOdometer 
{ 
    get { return _openingOdometer; } 
    set 
    { 
     _openingOdometer = value; 
     NotifyOfPropertyChange(() => OpeningOdometer); 
    } 
} 

// Implementation of IDataErrorInfo 
public string this[string columnName] 
{ 
    get 
    { 
     // This uses the System.ComponentModel.DataAnnotations placed on 
     // the OpeningOdometer property to produce an error string 
     // if the value of the property is in violation of any of the 
     // annotated rules. 
     return _valHelper.GetErrorsForProperty(columnName, this); 
    } 
} 
+1

¿Has encontrado el mejor enfoque para este Brian? : \ – GONeale

Respuesta

2

Puede obtener mejores respuestas si usted hace un esfuerzo para publicar un fragmento de su código/XAML relevante. Haría más fácil reproducir y eliminar gran parte de las conjeturas.

Pruebe la configuración ValidatesOnTargetUpdated="False" en sus reglas de validación y vea si eso ayuda.

+2

En realidad, no estoy utilizando ValidationRules, estoy implementando IDataErrorInfo. Debería haber incluido más detalles en la pregunta, disculpas. –

8

No pongo la lógica de validación en el indexador. Eso convierte el control sobre el tiempo de validación a la vista. En su esquema, la vista activa la validación cada vez que solicita la información de error de la propiedad. No sé todas las circunstancias en que eso va a pasar y apuesto a que tampoco.

En su lugar, puse la lógica de validación de una propiedad (más exactamente, la llamada a la función de validación) en su setter. Guardo el mensaje de error en un diccionario ingresado en el nombre de la propiedad, y hago que el indexador busque el mensaje de error para la propiedad.

De forma predeterminada, entonces, el mensaje de error está actualizado con el valor actual de la propiedad. Siempre que la vista actualice una propiedad y solicite su nueva información de error, obtendrá la respuesta correcta.

Pero también tiene un control bastante detallado sobre lo que realmente hay en ese diccionario. Si desea que una propiedad aparezca en la interfaz de usuario como válida, simplemente borre su mensaje de error en el diccionario (y suba PropertyChanged, para que la IU sepa que recibe el nuevo mensaje de error). O puede establecer los campos de respaldo de las propiedades en lugar de las propiedades mismas, omitiendo la validación, cuando construye el objeto de modelo de vista.

2

Sólo para indicar cómo he manejado esta utilización IDataErrorInfo ...

pongo una llamada a un nuevo método llamado OnDataUpdated() en cada colocador de mi propiedad vista de ruedas, tales como:

private string username; 
    public string Username 
    { 
     get { return username; } 
     set 
     { 
      username = value; 
      OnDataUpdated(); 
     } 
    } 

    private string password; 
    public string Password 
    { 
     get { return password; } 
     set 
     { 
      password = value; 
      OnDataUpdated(); 
     } 
    } 

a continuación, en el interior OnDataUpdated() marca un booleano ámbito privado como true indicando los datos ha cambiado por primera vez (FormType sólo era necesario para mi modelo de negocio):

private void OnDataUpdated() 
{ 
    dataChanged = true; 
    // .. Any other universal RaisePropertyChanged() events you may want to call to get your UI into sync. Eg. RaisePropertyChanged(() => CanConfirm); 
} 

Luego en mi propiedad del indexador IDataErrorInfo hago lo siguiente (lo divido para que 'ValidForm()' se pueda llamar manualmente para realizar la validación del formulario también.

public string this[string columnName] 
     { 
      get 
      { 
       string result = null; 
       if (columnName == "Username") 
       { 
        // If other payment amounts have fully paid for balance, and cash amount has been entered, deny 
        if (!ValidForm(FormType.Step1, columnName)) 
         result = "Please enter the username field."; 
       } 
       else if (columnName == "Password") 
       { 
        if (!ValidForm(FormType.Step1, columnName)) 
         result = "Please enter the password field."; 
       } 
       return result; 
      } 
     } 

     /// <summary> 
     /// Test if valid form. 
     /// </summary> 
     /// <param name="formType">Specify which form we should validate.</param> 
     /// <param name="columnName">If ommitted, entire form will be validated.</param> 
     /// <returns></returns> 
     private bool ValidForm(FormType formType, string columnName = null) 
     { 
      // This field is used to denote when data has changed on the form. 
      // If data has changed, we know we can activate any form validation. 
      // We do not activate the form validation until after a user has typed 
      // something in at least. 
      if (!dataChanged) return true; 

      var errors = false; 
      if (formType == FormType.Step1 && ((string.IsNullOrEmpty(columnName) || columnName == "Username") && string.IsNullOrEmpty(Username))) 
       errors = true; 
      if (formType == FormType.Step1 && ((string.IsNullOrEmpty(columnName) || columnName == "Password") && string.IsNullOrEmpty(Password))) 
       errors = true; 
      return !errors; 
     } 

Funciona beautifully. Ahora solo tengo estilos de validación que aparecen después de que un usuario edita el formulario.

Si quieres algo de la formación de hielo extra en el pastel, se puede comentar en mi RaisePropertyChanged(() => CanConfirm); en el método OnDataUpdated() y unir eso a su Confirmar Botón IsEnabled={Binding CanConfirm} con la propiedad asociada:

/// <summary> 
/// Can the user confirm step 1? 
/// </summary> 
public bool CanConfirm 
{ 
    get { return ValidForm(FormType.Step1); } 
} 

y el botón sólo estará habilitado cuando su formulario también es válido. :)

¡Disfrútalo! y la mejor de las suertes con el gigante que es WPF.

Cuestiones relacionadas