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

时间:2014-08-01 18:56:35

标签: c# xamarin.forms keyboard-events textinput

如何限制在Xamarin.Forms中的Entry控件中输入的长度和字符。我需要创建自定义控件吗?有没有办法从Entry(或其他控件)派生,所以我可以应用必要的每平台输入限制。

一个示例是一个数字字段,最多只能包含3个字符,仅限数字。

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

13 个答案:

答案 0 :(得分:18)

您可以在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
    }
  }

答案 1 :(得分:13)

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

答案 2 :(得分:9)

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

答案 3 :(得分:5)

我使用带有Bindable属性的自定义条目控件来获取大写和最大长度。

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

答案 4 :(得分:3)

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

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

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

答案 5 :(得分:2)

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

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

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

答案 6 :(得分:2)

我肯定会为这个

使用behvaior
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>

答案 7 :(得分:1)

看看Xamarin行为。有TextChangedBehavior.cs {{3}} 您可以使用模板开发自己的行为,以满足格式化的掩码文本输入字段。我为此目的开发了FormattedTextChangedBehavior : Behavior<Entry>

答案 8 :(得分:1)

Femil's 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 });

答案 9 :(得分:0)

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

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

答案 10 :(得分:0)

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

答案 11 :(得分:0)

实现此目的的最佳方法是使用行为,这将通过在达到最大长度后忽略任何进一步的输入来限制输入到输入项中的字符数。这篇文章解释了如何实现这一点,以及如何添加一个计数器,该计数器将向您的用户显示他们还剩下多少字符可以输入。当用户输入文本时,此计数器会实时更新。选中this post for more and very detailed information about this.

答案 12 :(得分:0)

使用最新版本的Xamarin表单,您只需设置条目或编辑器的 MaxLength 属性即可。这是增强功能的链接:

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