web-dev-qa-db-fra.com

Limitation de la longueur et des caractères du champ Entrée dans Xamarin.Forms

Comment puis-je limiter la longueur et les caractères entrés dans un contrôle d'entrée dans Xamarin.Forms. Dois-je créer un contrôle personnalisé? Existe-t-il un moyen de dériver de Entry (ou d'un autre contrôle) pour pouvoir appliquer les limitations d'entrée par plate-forme nécessaires?.

Un exemple serait un champ numérique limité à 3 caractères, chiffres uniquement.

La définition de la propriété Keyboard d'un contrôle Entry sur Keyboard.Numeric définit uniquement le clavier pour iOS. Cela ne limite pas la saisie de texte, c’est-à-dire que je peux toujours entrer des caractères non numériques. Je ne vois pas non plus de moyen de limiter la durée d'entrée.

24
Ken K

Vous pouvez limiter le nombre de caractères dans le champ de saisie comme indiqué ci-dessous,

  int restrictCount = <your restriction length> //Enter your number of character restriction
  Entry entry = new Entry();
  entry.TextChanged += OnTextChanged;

  void OnTextChanged(object sender, EventArgs e)
  {
    Entry entry = sender as Entry;
    String val = entry.Text; //Get Current Text

    if(val.Length > restrictCount)//If it is more than your character restriction
    {
     val = val.Remove(val.Length - 1);// Remove Last character 
     entry.Text = val; //Set the Old value
    }
  }
18
Femil Shajin

Je voudrais utiliser des comportements. Pour en savoir plus: https://developer.xamarin.com/guides/xamarin-forms/behaviors/creating/

Exemple: entrée avec clavier numérique. Mais il peut être utilisé pour n’importe quel clavier.

Utilisation de XAML:

<ContentPage
   xmlns:behaviors="clr-namespace:myApp.Behaviors;Assembly=myApp"

   <Entry
       Keyboard="Numeric"
       Text="{Binding EntryText}" >
       <Entry.Behaviors>
           <behaviors:EntryLengthValidatorBehavior MaxLength="3" />
       </Entry.Behaviors>
   </Entry>

Comportement

public class EntryLengthValidatorBehavior : Behavior<Entry>
{
    public int MaxLength { get; set; }

    protected override void OnAttachedTo(Entry bindable)
    {
        base.OnAttachedTo(bindable);
        bindable.TextChanged += OnEntryTextChanged;
    }

    protected override void OnDetachingFrom(Entry bindable)
    {
        base.OnDetachingFrom(bindable);
        bindable.TextChanged -= OnEntryTextChanged;
    }

    void OnEntryTextChanged(object sender, TextChangedEventArgs e)
    {
        var entry = (Entry)sender;

        // if Entry text is longer then valid length
        if (entry.Text.Length > this.MaxLength)
        {
            string entryText = entry.Text;

            entryText = entryText.Remove(entryText.Length - 1); // remove last char

            entry.Text = entryText;
        }
    }
}
13
Jana Filipenská

Vous pouvez simplement utiliser Binding; Par exemple, je veux conserver une valeur de paiement qui ne peut pas dépasser 100. J'ai donc écrit une classe.

puclic class Payment : INotifyPropertyChanged
{
    private int _amountDecimals;
    public int AmountDecimals
    {
        get
        {
            return _amountDecimals;
        }

        set
        {
            if (value <= 100)
            {
                _amountDecimals = value;
            }
            OnPropertyChanged();
        }
    public event PropertyChangedEventHandler PropertyChanged;

    protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
}

Donc, cette propriété va définir la valeur AmountDecimals si l'utilisateur entre une valeur jusqu'à ce qu'elle ne dépasse pas 100

Ensuite, définissez simplement la liaison via le code sur le constructeur de la page (ou à partir de xaml)

var myPayment =new Payment(); //this will hold page(view) data
BindingContext = myPayment;
var paymentEntry = new Entry();
paymentEntry.Keyboard = Keyboard.Numeric;
paymentEntry.SetBinding(Entry.TextProperty, "AmountDecimals");            

Ainsi, l'utilisateur entre une valeur numérique dans l'entrée, mais s'il tente d'entrer une valeur supérieure à 100, la liaison est simplement inversée. Vous pouvez simplement écrire votre code dans les propriétés de votre classe comme ceci (sur des setters). Donc, si vous voulez qu'une propriété ne comporte que 5 caractères, vous pouvez écrire quelque chose comme ceci (les codes peuvent être faux, je ne les ai pas compilés :))

    private string _name;
    public string Name
    {
        get
        {
            return _name;
        }

        set
        {
            if ((value!= null && value.length <= 5) || value == null)
            {
                _name = value;
            }
            OnPropertyChanged();
        }
9
Umut Bebek

J'ai utilisé un contrôle d'entrée personnalisé avec des propriétés Bindable pour les longueurs majuscules et majuscules.

Contrôle (MyEntry.cs)

class NewPaymentEntry : Entry
{
   public NewPaymentEntry()
    {
        base.TextChanged += EditText;
    }
    public void EditText(object sender, TextChangedEventArgs args)
    {
        Entry e = sender as Entry;
        String val = e.Text;

        if (string.IsNullOrEmpty(val))
            return;

        if (Uppercase )
            val = val.ToUpper();

        if(MaxLength > 0 && val.Length > MaxLength)
        {
                val = val.Remove(val.Length - 1);
        }
        e.Text = val;

    }

    public static readonly BindableProperty UppercaseProperty = BindableProperty.Create<MyEntry, bool>(p => p.Uppercase, false);

    public bool Uppercase
    {
        get
        {
            return (bool)GetValue(UppercaseProperty);
        }
        set
        {
            SetValue(UppercaseProperty, value);
        }
    }

    public static readonly BindableProperty MaxLengthProperty = BindableProperty.Create<MyEntry, int>(p => p.MaxLength, 0);

    public int MaxLength
    {
        get
        {
            return (int)GetValue(MaxLengthProperty);
        }
        set
        {
            SetValue(MaxLengthProperty, value);
        }
    }
}

Appelez-le de xaml comme

                  <MyEntry  Text="{Binding MyBindingProp}"
                            Uppercase="True"
                            MaxLength="11"/>
5
user2635746

Définissez une nouvelle entrée personnalisée avec les propriétés requises: 

public class CustomEntry : Entry
{
    public int MaxLength { get; set; }
    public bool IsNumeric { get; set; }
    public int MinValue { get; set; }
    public int MaxValue { get; set; }

    public CustomEntry()
    {

        // Initialize properties.
        IsNumeric = false;
        MaxLength = int.MaxValue;
        MinValue = int.MinValue;
        MaxValue = int.MaxValue;

        // Set the events.
        base.TextChanged += OnTextChanged;
    }

   public void OnTextChanged(object sender, TextChangedEventArgs e)
    {
        Entry entry = sender as Entry;

        // If empty, set it to empty string.
        if (string.IsNullOrWhiteSpace(e.NewTextValue))
        {
            entry.Text = string.Empty;
            return;
        }

        // Check if it is numeric.
        if (IsNumeric)
        {
            int value;
            var isValid = int.TryParse(e.NewTextValue, out value);

            if (!isValid)
            {
                entry.Text = e.OldTextValue;
                return;
            }

            // Check the min/max values.
            if (value > MaxValue || value < MinValue)
            {
                entry.Text = e.OldTextValue;
            }
        }

        // If not numeric, check the length.
        if (e.NewTextValue.Length > MaxLength)
            entry.Text = e.OldTextValue;
    }
}

Et pour l'utiliser en XAML:

   <controls:CustomEntry Text="{Binding months}" Keyboard="Numeric" IsNumeric="true" MaxLength="2" MinValue="1" MaxValue="12"/>

REMARQUE: au lieu de supprimer le dernier caractère, ce qui est le cas dans la plupart des réponses, il est préférable de définir le texte sur l'ancien texte, car l'utilisateur peut copier/coller plus d'un caractère dans la zone de texte.

3
A-Sharabiani

Je voudrais certainement utiliser un comportement pour cette

public class TextValidationBehavior : Behavior<Entry>
{
 // This can be bound to view model property to be informed
 public static readonly BindableProperty IsValidProperty = IsValidPropertyKey.BindableProperty;
    public bool IsValid
    {
        get { return (bool)base.GetValue(IsValidProperty); }
        private set { base.SetValue(IsValidPropertyKey, value); }
    }

// Attach delegate to text changed event
protected override void OnAttachedTo(Entry entry)
{
    entry.TextChanged += OnEntryTextChanged;
    base.OnAttachedTo(entry);
}
// Detach delegate from text changed event
protected override void OnDetachingFrom(Entry entry)
{
    entry.TextChanged -= OnEntryTextChanged;
    base.OnDetachingFrom(entry);
}

void OnEntryTextChanged(object sender, TextChangedEventArgs e)
{
    var text = e.NewTextValue;
    IsValid = Validate(text); // Implement this as needed
}
}

Puis utilisez-le dans xaml comme ceci

 <ContentPage xmlns:local="clr-namespace:Behaviors;Assembly=Behaviors" ... >

 <Entry Placeholder="Enter some text">
     <Entry.Behaviors>
        <local:TextValidationBehavior IsValid={Binding IsEntryValid} />
   </Entry.Behaviors>
 </Entry>
 </ContentPage>
2
joacar

Aucune propriété intégrée ne semble restreindre la longueur des caractères dans le contrôle Entry. Vous pouvez effectuer à la fois la limitation de texte et la saisie de caractères à l'aide de l'une des deux méthodes suivantes disponibles: -

  1. Oui - vous pouvez dériver directement de Entry pour créer votre propre dérivation, puis la personnaliser davantage, par exemple en vous connectant au gestionnaire d'événements TextChanged. Il n'y a pas de gestionnaire pour un appui sur une touche. Vous devez donc vérifier la validité des valeurs complètes transmises dans e.NewTextValue. Si la nouvelle entrée ne correspond pas à vos exigences, vous pouvez simplement configurer le .Text = e.OldTextValue pour revenir à la dernière entrée valide. 

  2. Si vous souhaitez vous connecter aux gestionnaires d'événements pour les contrôles natifs de chaque plate-forme, vous pouvez écrire vos propres contrôles de rendu personnalisés afin de disposer d'un contrôle plus fin.

2
Pete

Jetez un coup d'œil à Xamarin Behaviors. Il existe TextChangedBehavior.cs Que vous pouvez utiliser un modèle pour développer vos propres comportements afin de prendre en charge les champs de saisie de texte masqués formatés. J'ai développé FormattedTextChangedBehavior : Behavior<Entry> uniquement dans ce but.

1
Mark Carew

Une suite de réponse de Femil :

Voici un contrôle personnalisé pour limiter le nombre de caractères, mais il pourrait être utilisé pour tout ce pour quoi vous voulez utiliser TextChanged:

public class CustomEntry : Entry
{
    private CustomEntryParams parameters { get; set; }

    public CustomEntry(CustomEntryParams customParams)
    {
        if (customParams.MaxLength > 0)
        {
            base.TextChanged += EnforceMaxLength;
            parameters = customParams;
        }
    }

    public void EnforceMaxLength(object sender, TextChangedEventArgs args)
    {
        Entry e = sender as Entry;
        String val = e.Text;

        if (val.Length > parameters.MaxLength)
        {
            val = val.Remove(val.Length - 1);
            e.Text = val;
        }
    }
}

public class CustomEntryParams {
    public int MaxLength { get; set; }
}

N'essayez pas de l'utiliser dans le code XAML, vous recevrez une erreur d'analyse, mais utilisez-le dans le codebehind:

new CustomEntry(new CustomEntryParams { MaxLength = 5 });
1
ParanoidCoder
public class AppEntry : Entry
{
    public AppEntry()
    {
        TextChanged += _EnforceMaxLength;
    }

    public int? MaxLength { get; set; }

    private void _EnforceMaxLength(object sender, TextChangedEventArgs args)
    {
        if (!MaxLength.HasValue) return;

        var e = sender as Entry;
        if (e == null)
            return;

        var val = e.Text;

        if (!(val.Length > MaxLength)) return;

        val = val.Remove(val.Length - 1);
        e.Text = val;
    }
}

usage:

var element = new AppEntry
{
    HorizontalOptions = LayoutOptions.FillAndExpand,
    ...
    MaxLength = 123,
};
0

Vous pouvez définir les filtres comme ci-dessous dans la méthode OnElementChanged à partir du moteur de rendu personnalisé.

this.Control.SetFilters(new Android.Text.IInputFilter[] { new Android.Text.InputFilterLengthFilter(MaxLength)});
0
Shyju M

Le meilleur moyen d'implémenter cela est d'utiliser des comportements, qui limiteront le nombre de caractères saisis dans votre entrée en ignorant toute autre entrée après que le nombre maximal de caractères ait été atteint. Cet article explique comment y parvenir et comment ajouter un compteur qui indiquera à vos utilisateurs le nombre de caractères qu’ils ont à saisir. ce compteur est mis à jour en temps réel lorsque l'utilisateur saisit des textes. Vérifiez ce post pour plus d'informations très détaillées à ce sujet.

0
Damien Doumer