Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it possible specify Xamarin Forms Entry Numeric Keyboard without comma or decimal point separator?

I have to create a form in which the user must input his age. I would like to use a numeric keyboard:

    <Entry
        x:Name="AgeEntry"
        VerticalOptions="FillAndExpand"
        HorizontalOptions="FillAndExpand"
        Keyboard="Numeric"
    />

but it shows even the decimal point character, I'd like to show only numbers...

like image 287
Falco Avatar asked Jun 10 '17 16:06

Falco


4 Answers

To restrict the Entry to only accept numbers you could use a Behavior or a Trigger.

Both of those will react to a user typing into them. So for your use, you could have the trigger or behavior look for any characters that are not numbers and remove them.

Something like this for a behavior (note that I wrote all this on SO and did not try compiling it, let me know if it does not work):

using System.Linq;
using Xamarin.Forms;

namespace MyApp {

    public class NumericValidationBehavior : Behavior<Entry> {

        protected override void OnAttachedTo(Entry entry) {
            entry.TextChanged += OnEntryTextChanged;
            base.OnAttachedTo(entry);
        }

        protected override void OnDetachingFrom(Entry entry) {
            entry.TextChanged -= OnEntryTextChanged;
            base.OnDetachingFrom(entry);
        }

        private static void OnEntryTextChanged(object sender, TextChangedEventArgs args) 
        {

            if(!string.IsNullOrWhiteSpace(args.NewTextValue)) 
            { 
                 bool isValid = args.NewTextValue.ToCharArray().All(x=>char.IsDigit(x)); //Make sure all characters are numbers

                ((Entry)sender).Text = isValid ? args.NewTextValue : args.NewTextValue.Remove(args.NewTextValue.Length - 1);
            }
        }


    }
}

Then in your XAML:

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
         xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
         xmlns:local="clr-namespace:MyApp;assembly=MyApp"> <!-- Add the local namespace so it can be used below, change MyApp to your actual namespace -->

  <Entry x:Name="AgeEntry"
         VerticalOptions="FillAndExpand"
         HorizontalOptions="FillAndExpand"
         Keyboard="Numeric">
    <Entry.Behaviors>
      <local:NumericValidationBehavior />
    </Entry.Behaviors>
  </Entry>

</ContentPage>
like image 185
hvaughan3 Avatar answered Oct 03 '22 11:10

hvaughan3


To me the simple solution is just to add a TextChanged handle to the Entry (this is UI specific code so does not break MVVM)

   <Entry Text="{Binding BoundValue}" Keyboard="Numeric" TextChanged="OnTextChanged"/>

Then in code behind

    private void OnTextChanged(object sender, TextChangedEventArgs e)
    {
        //lets the Entry be empty
        if ( string.IsNullOrEmpty(e.NewTextValue) ) return;

        if ( !double.TryParse(e.NewTextValue, out double value) )
        {
            ((Entry) sender).Text = e.OldTextValue;
        }
    }

Change in int.Parse if need an integer

like image 39
Joe H Avatar answered Oct 03 '22 11:10

Joe H


I was facing this too, but the best way to implement this is through behaviors, here is an article which shows you in detail how to implement this and even more, like limiting the value of the number entered to a given value you set in your XAML.

like image 25
Damien Doumer Avatar answered Oct 03 '22 12:10

Damien Doumer


if (!string.IsNullOrWhiteSpace(args.NewTextValue))
{
    bool isValid = args.NewTextValue.ToCharArray().All(char.IsDigit);

    ((Editor)sender).Text = isValid ? args.NewTextValue : args.OldTextValue;
}

This prevents adding any non digit char into the Editor no matter where you added it. So if your cursor was in the middle of your number and you got for example 21h3 in @hvaughan3's answer you would just remove the last char giving you 21h with the non digit still being present.

My answer will just use the value you had before adding the non digit char (213).

But keep in mind! If you put this in a behavior and react to editor.TextChanged Event, this is still gonna change the Text for a brief second to the invalid value since this event triggers when it ALREADY was set. this is no OnTextChanging event. Same for @hvaughan3's answer. To prevent any issues you might get because of this, for example because you're also listening to OnTextChanged in Code behind, just add this line before working with the new text value

if (!editor.Text.All(char.IsDigit)) return;
like image 20
Anna S. Avatar answered Oct 03 '22 12:10

Anna S.