Ограничение длины ввода и символов для поля ввода в Xamarin.Forms

Как я могу ограничить длину и символы, введенные в элемент управления Entry в Xamarin.Forms. Нужно ли создавать пользовательский элемент управления? Есть ли способ, который я могу извлечь из Entry (или другого элемента управления), чтобы я мог применить необходимые ограничения для каждой платформы.

Примером может служить числовое поле, которое ограничено максимум 3 символами, только цифры.

Настройка свойства Keyboard элемента управления Entry на Keyboard.Numeric устанавливает клавиатуру для iOS. Он не ограничивает фактическую запись текста - то есть я все еще могу вводить символы без цифр. Я также не вижу способа ограничить длину записи.

Ответы

Ответ 1

Вы можете ограничить количество charecters в поле Entry, как указано ниже,

  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
    }
  }

Ответ 2

Я бы использовал Behaviors. Подробнее об этом: https://developer.xamarin.com/guides/xamarin-forms/behaviors/creating/

Пример для ввода с цифровой клавиатурой. Но он может использоваться для любой клавиатуры.

Использование 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>

Поведение

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;
        }
    }
}

Ответ 3

Вы можете просто использовать Binding; Например, я хочу сохранить значение платежа, которое не может превышать 100. Поэтому я написал класс

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));
    }
}

Таким образом, это свойство будет устанавливать значение AmountDecimals, если пользователь вводит значение, пока оно не будет превышать 100

Затем просто установите привязку через код на конструкторе страницы (или из 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");            

Таким образом, пользователь вводит числовое значение для записи, но если он пытается ввести значение более 100, привязка просто вернет его к старому значению. Вы можете просто написать свой код для своих свойств класса, как это (на сеттерах). Поэтому, если вы хотите, чтобы какое-то свойство носило только 5 символов, вы можете написать что-то вроде этого (коды могут быть неправильными, я их не скомпилировал:))

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

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

Ответ 4

Я использовал настраиваемый элемент управления с свойствами Bindable для прописной и максимальной длины.

Управление (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);
        }
    }
}

Вызовите его из xaml, например

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

Ответ 5

Определите новую пользовательскую запись с требуемыми свойствами:

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;
    }
}

И использовать его в XAML:

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

ПРИМЕЧАНИЕ. Вместо удаления последнего символа, который имеет место в большинстве ответов, более безопасно устанавливать текст в старый текст, поскольку пользователь может копировать/переносить больше, чем символ в текстовое поле.

Ответ 6

В элементе управления Entry отсутствуют встроенные свойства для ограничения символа/длины. Вы можете выполнить ограничение текста и ввод символов одним из следующих двух доступных способов:

  1. Да - вы можете получить его непосредственно из Entry, чтобы создать свой собственный производный от него, а затем настроить его, например, подключив обработчик событий TextChanged. Нет обработчика для нажатия клавиши, поэтому вам нужно будет проверить правильность полных значений, переданных в e.NewTextValue. Если новая запись не соответствует вашим требованиям, вы можете просто установить .Text = e.OldTextValue, чтобы вернуться к последней действительной записи.

  2. Если вы хотите подключиться к обработчикам событий для собственных элементов управления каждой платформы, вы можете написать свои собственные пользовательские элементы управления рендерингом, чтобы иметь более точный контроль.

Ответ 7

Я определенно использовал бы для этого

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
}
}

Затем используйте его в xaml, как этот

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

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

Ответ 8

Посмотрите на Xamarin Behaviors. Существует TextChangedBehavior.cs что вы можете использовать шаблон для разработки своего собственного поведения, чтобы обслуживать отформатированные поля ввода скрытых текстовых полей. Для этой цели я разработал FormattedTextChangedBehavior : Behavior<Entry>.

Ответ 9

Продолжение Femil answer:

Здесь пользовательский элемент управления для ограничения количества символов, но он может использоваться для всего, что вы хотите использовать 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; }
}

Не пытайтесь использовать это в XAML, вы получите ошибку парсера, вместо этого используйте его в коде:

new CustomEntry(new CustomEntryParams { MaxLength = 5 });

Ответ 10

Вы можете установить фильтры, как показано ниже, в методе OnElementChanged из пользовательского средства визуализации

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

Ответ 11

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;
    }
}

использование:

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

Ответ 12

Лучший способ реализовать это - использовать поведение, которое будет ограничивать количество символов, вводимых в вашу запись, игнорируя любые дальнейшие вводы после достижения максимальной длины. В этом посте объясняется, как этого добиться, а также как добавить счетчик, который будет показывать вашим пользователям, сколько символов осталось для ввода. этот счетчик обновляется в реальном времени по мере ввода текста пользователем. Проверьте этот пост для получения более подробной информации об этом.