2011-05-25 11 views
12

Tengo un cuadro de texto vinculado a una clase con una propiedad de tipo Timespan y he escrito un convertidor de valor para convertir una cadena en TimeSpan.Cómo manejar una excepción en el convertidor de valor para que se muestre un mensaje de error personalizado

Si no se ingresa un número en el cuadro de texto, me gustaría que se muestre un mensaje de error personalizado (en lugar de la 'cadena de entrada predeterminada está en el formato incorrecto').

El código convertidor es:

public object ConvertBack(
     object value, 
     Type targetType, 
     object parameter, 
     CultureInfo culture) 
    { 
     try 
     { 
      int minutes = System.Convert.ToInt32(value); 
      return new TimeSpan(0, minutes, 0); 
     } 
     catch 
     { 
      throw new FormatException("Please enter a number"); 
     } 
    } 

he puesto 'ValidatesOnExceptions = True' en la unión XAML.

Sin embargo, me he encontrado con el siguiente artículo de MSDN, lo que explica por qué el anterior no funcionará:.

"El motor de enlace de datos no significa capturar las excepciones que se tiran por un convertidor suministrado por el usuario Cualquier excepción que es lanzado por el método Convertir, o cualquier excepción no detectada lanzada por métodos que llama el método Convert, se tratan como errores de tiempo de ejecución "

He leído que 'ValidatesOnExceptions capta excepciones en TypeConverters, entonces mis preguntas específicas son:

  • ¿Cuándo utilizar un TypeConverter durante un ValueConverter
  • Suponiendo una TypeConverter no es la respuesta a la cuestión anterior, ¿cómo puedo mostrar mi mensaje de error personalizado en la interfaz de usuario
+0

Los errores en los datos de WPF de unión se supone que debe ser transparente, de modo que un pequeño error no mata a toda la aplicación o interfaz de usuario.Puede registrar la excepción, pero intentar hacer cualquier otra cosa derrota el diseño del enlace de datos. – slugster

Respuesta

9

me gustaría utilizar un ValidationRule de que, de esta manera, el convertidor puede estar seguro de que la conversión funciona, ya que solo se llama si la validación tiene éxito y puede utilizar la propiedad adjunta Validation.Errors que contendrá los errores que su ValidationRule crea si la entrada no es de la manera que desea.

p. Ej. (nota la descripción de unión)

<TextBox> 
    <TextBox.Style> 
     <Style TargetType="{x:Type TextBox}"> 
      <Style.Triggers> 
       <Trigger Property="Validation.HasError" Value="True"> 
        <Setter Property="Background" Value="Pink"/> 
        <Setter Property="ToolTip" Value="{Binding RelativeSource={RelativeSource Self}, Path=(Validation.Errors)[0].ErrorContent}"/> 
       </Trigger> 
      </Style.Triggers> 
     </Style> 
    </TextBox.Style> 
    <TextBox.Text> 
     <Binding Path="Uri"> 
      <Binding.ValidationRules> 
       <vr:UriValidationRule /> 
      </Binding.ValidationRules> 
      <Binding.Converter> 
       <vc:UriToStringConverter /> 
      </Binding.Converter> 
     </Binding> 
    </TextBox.Text> 
</TextBox> 

screenshot

+0

Gracias HB, voy a intentarlo – sturdytree

+1

Desafortunadamente, esto solo funciona de una manera. Las ValidationRules solo se ejecutan en el viaje de regreso * desde la UI a la fuente de datos *. No puede usar esto para interceptar o manejar excepciones lanzadas por los convertidores en el método Convert. – Will

+0

@Will: Creo que los convertidores no deben arrojar ninguna excepción si tiene una regla de validación personalizada; cuando los datos provienen del modelo, deben ser válidos de todos modos y si el usuario ingresa datos no válidos, no se debe llamar al convertidor ya que ValidationRule no lo deja pasar. –

6

que usa la validación y el convertidor de aceptar null y los números

XAML:

<TextBox x:Name="HeightTextBox" Validation.Error="Validation_Error"> 
    <TextBox.Text> 
     <Binding Path="Height" 
       UpdateSourceTrigger="PropertyChanged" 
       ValidatesOnDataErrors="True" 
       NotifyOnValidationError="True" 
       Converter="{StaticResource NullableValueConverter}"> 
      <Binding.ValidationRules> 
       <v:NumericFieldValidation /> 
      </Binding.ValidationRules> 
     </Binding> 
    </TextBox.Text> 
</TextBox> 

código subyacente:

private void Validation_Error(object sender, ValidationErrorEventArgs e) 
{ 
    if (e.Action == ValidationErrorEventAction.Added) 
     _noOfErrorsOnScreen++; 
    else 
     _noOfErrorsOnScreen--; 
} 

private void Confirm_CanExecute(object sender, CanExecuteRoutedEventArgs e) 
{ 
    e.CanExecute = _noOfErrorsOnScreen == 0; 
    e.Handled = true; 
} 

ReglaDeValidación:

public class NumericFieldValidation : ValidationRule 
{ 
    private const string InvalidInput = "Please enter valid number!"; 

    // Implementing the abstract method in the Validation Rule class 
    public override ValidationResult Validate(object value, System.Globalization.CultureInfo cultureInfo) 
    { 
     float val; 
     if (!string.IsNullOrEmpty((string)value)) 
     { 
      // Validates weather Non numeric values are entered as the Age 
      if (!float.TryParse(value.ToString(), out val)) 
      { 
       return new ValidationResult(false, InvalidInput); 
      } 
     } 

     return new ValidationResult(true, null); 
    } 
} 

Convertidor:

public class NullableValueConverter : IValueConverter 
{ 
    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) 
    { 
     return value; 
    } 

    public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) 
    { 
     if (string.IsNullOrEmpty(value.ToString())) 
      return null; 
     return value; 
    } 
} 
+0

¡Gracias por esta solución completa! Para cualquiera que tenga problemas para ejecutar Validation_Error, asegúrese de incluir NotifyOnValidationErrors en XAML. Como ya tenía la validación de error de estilo IDataErrorInfo (y por lo tanto ValidateOnDataErrors), pasé por encima del XAML y omití este detalle. – Tim

Cuestiones relacionadas