繁体   English   中英

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

[英]Restricting input length and characters for Entry field in Xamarin.Forms

如何限制在 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
    }
  }

我会使用行为。 更多相关信息: 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;
        }
    }
}

你可以只使用绑定; 例如我想持有一个不能超过 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 值

然后只需通过页面构造函数(或来自 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"/>

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

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

  2. 如果您想连接到每个平台本机控件的事件处理程序,您可以编写自己的自定义渲染器控件以获得更好的控制。

使用所需的属性定义一个新的自定义条目:

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

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

我肯定会为此使用行为

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 中使用它,您将收到解析器错误,而是在代码隐藏中使用它:

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM