限制Xamarin.Forms中Entry字段的输入长度和字符

本文关键字:输入 字符 字段 Xamarin Forms Entry 限制 | 更新日期: 2023-09-27 18:16:13

如何限制Xamarin.Forms中Entry控件中输入的长度和字符。我需要创建自定义控件吗?有没有一种方法可以从Entry(或另一个控件(派生,这样我就可以应用必要的每个平台的输入限制。

例如,一个数字字段最多限制为3个字符,仅限数字。

将Entry控件的Keyboard属性设置为Keyboard。Numeric仅为iOS设置键盘。它不限制实际的文本输入,即我仍然可以输入非数字字符。我也看不出有什么办法可以限制进入的时间。

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

限制Xamarin.Forms中Entry字段的输入长度和字符

我会使用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;
        }
    }
}

您可以使用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));
    }
}

因此,如果用户输入的值不超过100 ,此属性将设置AmountDecimals值

然后通过Page构造函数上的代码(或从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的值,则绑定只需将其反转为旧值。您可以像这样(在setter上(将代码写入类的属性中。因此,如果你想让某些属性只包含5个字符,你可以写这样的东西(代码可能是错误的,我没有编译它们:(

    private string _name;
    public string Name
    {
        get
        {
            return _name;
        }
        set
        {
            if ((value!= null && value.length <= 5) || value == null)
            {
                _name = value;
            }
            OnPropertyChanged();
        }

我使用了一个自定义条目控件,该控件具有大写和最大长度的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"/>

定义一个具有所需属性的新自定义条目:

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"/>

注意:与大多数答案中的最后一个字符不同,将文本设置为旧文本更安全,因为用户可能会将多个字符复制到文本框中。

Entry控件中似乎没有限制字符/长度的内置属性。您可以通过以下两种可用方法之一完成文本限制和字符输入:-

  1. 是-您可以直接从Entry派生,创建自己的派生,然后进一步自定义它,例如挂接到TextChanged事件处理程序。按键没有处理程序,因此您必须对传递到e.NewTextValue中的完整值进行有效性检查。如果新条目与您的要求不匹配,则只需设置.Text=e.OldTextValue即可恢复到上一个有效条目。

  2. 如果您想挂接到每个平台本机控件的事件处理程序中,您可以编写自己的自定义呈现器控件以获得更精细的控制。

我肯定会为这个使用behwaior

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>

了解Xamarin行为。存在TextChangedBehavior.cs您可以使用一个模板来开发自己的行为,以满足格式化的屏蔽文本输入字段的需要。我开发FormattedTextChangedBehavior : Behavior<Entry>就是为了这个目的。

Femil答案的延续:

这里有一个用于限制字符数的自定义控件,但它可以用于任何您想使用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中使用它,你会收到一个语法分析器错误,而是在codeehind:中使用它

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

您可以在自定义渲染器的OnElementChanged方法中设置如下过滤器

this.Control.SetFilters(new Android.Text.IInputFilter[] { new Android.Text.InputFilterLengthFilter(MaxLength)});
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,
};

实现这一点的最佳方法是使用行为,这将通过在达到最大长度后忽略任何进一步的输入来限制输入条目的字符数。这篇文章解释了如何实现这一点,以及如何添加一个计数器,该计数器将向用户显示他们还有多少字符需要输入。该计数器在用户输入文本时实时更新。查看这篇文章,了解更多和非常详细的信息。

使用最新版本的Xamarin Forms,您只需设置条目或编辑器的MaxLength属性。以下是增强的链接:

https://github.com/xamarin/Xamarin.Forms/issues/1663