问题
How can I restrict the length and characters entered in an Entry control in Xamarin.Forms. Do I need to create a custom control? Is there a way I can derive from Entry (or another control) so I can apply the necessary per-platform input limitations.
An example would be a numeric field that is restricted to a maximum of 3 characters, digits only.
Setting the Keyboard property of an Entry control to Keyboard.Numeric only sets the keyboard for iOS. It does not restrict the actual text entry - i.e. I can still enter non-digit characters. Nor do I see a way to limit the length of entry.
回答1:
You can restrict the number of charecters in the Entry field as given below,
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:
I would use Behaviors. More about it: https://developer.xamarin.com/guides/xamarin-forms/behaviors/creating/
Example is for Entry with Numeric keyboard. But it can be used for any keyboard.
XAML usage:
<ContentPage
xmlns:behaviors="clr-namespace:myApp.Behaviors;assembly=myApp"
<Entry
Keyboard="Numeric"
Text="{Binding EntryText}" >
<Entry.Behaviors>
<behaviors:EntryLengthValidatorBehavior MaxLength="3" />
</Entry.Behaviors>
</Entry>
Behavior
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:
You can just use Binding; For example i want to hold a payment value that can not exceed 100. So i wrote a class
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));
}
}
So this property will set AmountDecimals value if user enters a value until it not exceeds 100
Then just set binding via code on Page constructor(or from 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");
So user enters a numeric value to the entry, but if he/she tries to enter a value more than 100, binding just reverse it to old value. You can just write your code to your class's properties like this (on setters). So if you want to some property to carry only 5 characters you can write something like this (codes can be wrong i did not compiled them :) )
private string _name;
public string Name
{
get
{
return _name;
}
set
{
if ((value!= null && value.length <= 5) || value == null)
{
_name = value;
}
OnPropertyChanged();
}
回答4:
I used a custom entry control with Bindable properties for uppercase and maximum length.
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);
}
}
}
Call it from xaml like
<MyEntry Text="{Binding MyBindingProp}"
Uppercase="True"
MaxLength="11"/>
回答5:
Define a new Custom Entry with the required properties:
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;
}
}
And to use it in XAML:
<controls:CustomEntry Text="{Binding months}" Keyboard="Numeric" IsNumeric="true" MaxLength="2" MinValue="1" MaxValue="12"/>
NOTE: instead of removing the last character which is the case in most answers, it is safer to set the text to the old text, since the user might copy/past more than a character into the textbox.
回答6:
I would definitely use a behvaior for this
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
}
}
Then use it in xaml like this
<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:
There appears no in-built properties to restrict character / length in the Entry control. You could accomplish both the text limiting and character input via one of the following two methods available:-
Yes - you can derive directly from Entry to create you own derivation of this and then customize it further, for instance hooking into the TextChanged event handler. There is no handler for a key-press, so you would have to do your validity checking on the complete values passed into e.NewTextValue. If the new entry doesn't match within your requirements you could then just set the .Text=e.OldTextValue to revert to the last valid entry.
If you wanted to hook into the event handlers for the each platform native-controls you could write your own custom renderer controls to have finer control.
回答8:
Have a look at Xamarin Behaviors. There is TextChangedBehavior.cs
that you can use a template for developing your own behaviors to cater for formatted masked text entry fields. I have developed FormattedTextChangedBehavior : Behavior<Entry>
for just this purpose.
回答9:
A continuation of Femil's answer:
Here's a custom control for limiting the number of characters, but it could be used for anything you want to use TextChanged for:
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; }
}
Don't try to use this in the XAML, you will receive a parser error, instead use it in the codebehind:
new CustomEntry(new CustomEntryParams { MaxLength = 5 });
回答10:
You can set the filters as below in the OnElementChanged method from the custom renderer
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;
}
}
usage:
var element = new AppEntry
{
HorizontalOptions = LayoutOptions.FillAndExpand,
...
MaxLength = 123,
};
回答12:
The best way to implement this is to use behaviors, which will limit the number of character entered to your Entry by ignoring any further input after the max lngth has been reached. This post explains how to accomplish this and also how to add a counter which will display to your users how many characters they have left to input. this counter updates in realtime as the user input texts. Check this post for more and very detailed information about this.
来源:https://stackoverflow.com/questions/25086881/restricting-input-length-and-characters-for-entry-field-in-xamarin-forms