Bonjour,
Lorsqu'on met l'attribut de validation StringLength sur une propriété qui est liée à un TextBox, on peut désirer que la propriété MaxLength du TextBox soit automatiquement placée à cette valeur. De cette façon, au lieu d'avoir un message d'erreur lorsque le nombre de caractères excède le maximum, l'usager ne peut tout simplement pas entrer plus de caractères que le maximum.
Pour arriver à intégrer cette logique, il n'y a pas beaucoup de points d'entrées. Un Binding custom n'est pas chargé avec la source via le constructeur, et on n’a pas accès au TextBox au niveau de l'entité. On ne peut pas non plus retirer le dernier caractère au nouveau de l'entité car lorsqu'un caractère serait ajouter ailleurs qu'à la fin, c'est le dernier caractère de la chaine qui serait retiré (à moins d'avoir un buffer mais ce n'est pas très propre).
Alors voici la solution qui a été retenu. On appel un Converter qui s'occupe de faire la mise à jour de la propriété MaxLength. Au niveau du Converter nous avons accès à toute l'information dont on a besoin.
Voici le code du Converter
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
if (value is TextBox)
{
((TextBox)value).DataContextChanged += new System.Windows.DependencyPropertyChangedEventHandler(MaxLengthConverter_DataContextChanged);
return ((TextBox)value).MaxLength;
}
return null;
}
private void MaxLengthConverter_DataContextChanged(object sender, System.Windows.DependencyPropertyChangedEventArgs e)
{
TextBox currentTextBoxInConversion = (TextBox)sender;
Binding textBoxTextPropertyBinding = BindingOperations.GetBinding(currentTextBoxInConversion, TextBox.TextProperty);
if (textBoxTextPropertyBinding != null && e.NewValue != null)
{
PropertyInfo propertyBoundToText = e.NewValue.GetType().GetProperty(textBoxTextPropertyBinding.Path.Path);
if (propertyBoundToText != null)
{
object[] foundValidationStringLengthAttributes = propertyBoundToText.GetCustomAttributes(typeof(ValidationStringLengthAttribute), true);
if (foundValidationStringLengthAttributes != null && foundValidationStringLengthAttributes.Count() > 0)
{
int maxLength = ((ValidationStringLengthAttribute)foundValidationStringLengthAttributes[0]).Max;
currentTextBoxInConversion.MaxLength = maxLength;
}
}
}
}
Voici comment il devrait être intégré.
<xxxxxx.Resources>
<local:AutoMaxLengthConverter x:Key="MaxLengthConverter"/>
<Style TargetType="TextBox">
<Setter Property="MaxLength"
Value="{Binding RelativeSource={RelativeSource Self},
Converter={StaticResource MaxLengthConverter}}">
</Setter>
</Style>
</xxxxxx.Resources>
Dans l'exemple ici, aucune clef n'est spécifiée donc tous les TextBox seront affectés. Ajouté une clef permettrait de ciblé mais empêcherait un lien à d'autre Style. On peut également l'ajouter à un Style qui serait déjà utilisé par les TextBox. En gros, on fait comme on veut.