web-dev-qa-db-ja.com

Xamarin.Formsの入力フィールドの入力の長さと文字を制限する

Xamarin.Formsのエントリコントロールに入力する長さと文字を制限するにはどうすればよいですか。カスタムコントロールを作成する必要がありますか? Entry(または別のコントロール)から派生できる方法があるので、必要なプラットフォームごとの入力制限を適用できます。

例は、最大3文字、数字のみに制限されている数値フィールドです。

EntryコントロールのKeyboardプロパティをKeyboard.Numericに設定すると、iOSのキーボードのみが設定されます。実際のテキスト入力を制限しません。つまり、数字以外の文字を入力できます。エントリーの長さを制限する方法も見当たりません。

25
Ken K

以下に示すように、入力フィールドの文字数を制限できます。

  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
    }
  }
18
Femil Shajin

ビヘイビアを使用します。それについての詳細: 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;
        }
    }
}
13

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値を設定します

次に、ページコンストラクター(または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();
        }
9
Umut Bebek

大文字と最大長のバインド可能なプロパティを持つカスタムエントリコントロールを使用しました。

コントロール(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
user2635746

必要なプロパティを使用して新しいカスタムエントリを定義します。

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

注:ほとんどの回答にある最後の文字を削除する代わりに、テキストを古いテキストに設定する方が安全です。ユーザーが1文字以上をテキストボックスにコピー/ペーストする可能性があるためです。

3
A-Sharabiani

私は間違いなくこの動作を使用します

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>
2
joacar

Entryコントロールの文字/長さを制限する組み込みプロパティはありません。次の2つの方法のいずれかを使用して、テキスト制限と文字入力の両方を実行できます。

  1. はい-Entryから直接派生して、独自の派生を作成し、さらにカスタマイズします。たとえば、TextChangedイベントハンドラーにフックします。キーを押すためのハンドラはないため、e.NewTextValueに渡された完全な値に対して有効性チェックを行う必要があります。新しいエントリが要件内で一致しない場合は、。Text = e.OldTextValueを設定して、最後の有効なエントリに戻すことができます。

  2. 各プラットフォームのネイティブコントロールのイベントハンドラーにフックする場合は、独自のカスタムレンダラーコントロールを作成して、よりきめ細かな制御を行うことができます。

2
Pete

Xamarin Behaviorsをご覧ください。 TextChangedBehavior.cs があります。テンプレートを使用して、書式設定されたマスクされたテキスト入力フィールドに対応する独自の動作を開発できます。私はFormattedTextChangedBehavior : Behavior<Entry>ちょうどこの目的のため。

1
Mark Carew

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 });
1
ParanoidCoder
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,
};

カスタムレンダラーのOnElementChangedメソッドで、以下のようにフィルターを設定できます

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

これを実装する最良の方法は、ビヘイビアを使用することです。これにより、最大lngthに達した後はそれ以上の入力を無視して、エントリに入力される文字数が制限されます。この投稿では、これを実現する方法と、入力するために残された文字数をユーザーに表示するカウンターを追加する方法について説明します。ユーザーがテキストを入力すると、このカウンターはリアルタイムで更新されます。 これについてのより詳細な情報については、この投稿をご覧ください。

0
Damien Doumer