Accueil

Range Validator sur un DateTime

by Jean-Camille Mercier 29. avril 2013 10:13

Hier j'ai décrit les différents validateurs possibles du framework ici. Voici maintenant le cas un peu plus spécifique du DateTime non nullable. En effet, la valeur par défaut d'un DateTime est "01/01/0001" ce qui pose deux problèmes : cette valeur n'est pas sauvegardable en base de données car SQL n'accepte pas les date en dessous de l'année 1753, et en plus cette date est totalement incompréhensible par l'utilisateur lambda.

  • Empêcher la saisie d'une date trop petite

Il faut donc mettre un Validateur de type Range sur la date ce qui peut être fait de cette manière : 

[Range(typeof(DateTime), SqlDateTime.MinValue.ToString(), SqlDateTime.MaxValue.ToString(), 
                         ErrorMessage="Merci de saisir une date valide")]
public DateTime MaDate { get; set; }

ou plus simplement :

[Range(typeof(DateTime), "01/01/1900", "01/01/3000", 
                         ErrorMessage="Merci de saisir une date valide")]
public DateTime MaDate { get; set; }
  • Ne pas afficher "01/01/0001"
Pour saisir la date, j'utilise une RadDatePicker WPF de Telerik. Si je bind directement la SelectedDate à "MaDate", on voit cette valeur minimale s'afficher, l'astuce réside donc simplement à faire un Converter, qui, positionné sur le binding, fera croire à l'UI que la valeur est null alors que c'est DateTime.MnValue :
// <summary>
// Pour les RadDateTimePicker il faut que la date soit null pour afficher 
// le message "veuillez saisir une date". Donc les DateTime non null, 
// on ajoute ce converter pour transformer la valeur MinValue en null
// </summary>
public class DateTimeNullValueConverter : IValueConverter
{
  object Convert(object value, Type targetType, object parameter, CultureInfo culture)
  {
    if (value is DateTime && (DateTime)value == DateTime.MinValue)
      return null;
    else
      return value;
  }

  object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
  {
    if (value == null)
      return DateTime.MinValue;
    else
      return value;
  }
}
J'ai fait de même pour les affichage : un Converter qui retourne "xx/xx/xxxx" lorsque la date est MinValue ce qui lui montre bien qu'il n'a encore rien saisie. Voici le rendu final :
 
 
 
 En quelques lignes on obtient un résultat impeccable !