Xamarin forms limit number of decimal places in an entry field

Viewed 2694

I have an entry field inside of a collection view cell. The entry field should accept numeric value only with certain decimal places. I don't want more input if they exceed the decimal places. The decimal places vary for each cell. How do I create this validation in Model or using behaviour/trigger?

Currently, my code is like this

<Entry Placeholder="Quantity"
       Keyboard="Numeric"
       Text="{Binding EnteredQuantity, Mode=TwoWay}"/>

And in the model part, I am doing this

private string enteredQuantity = "1";

        public string EnteredQuantity
        {
            get => enteredQuantity;

            set
            {
                if (!decimal.TryParse(value, out decimal parsedQuantity))
                {
                    enteredQuantity = "1";
                    OnPropertyChanged(enteredQuantity);
                }
                else
                {
                    if (parsedQuantity > 9999.99M)
                    {
                        enteredQuantity =string.Format("9999.99", parsedQuantity);
                        OnPropertyChanged(enteredQuantity);
                    }
                    else
                    {
                        string formatString = "{" + "0:0.".PadRight(4 + (int) BaseDecimalPlaces, '#') + "}"; //Format of {0:0.##}
                        if (IsAlternateUnitUsed && selectedUnit.Value == "A")
                        {
                            formatString = "{" + "0:0.".PadRight(4 + (int) AlternateDecimalPlaces, '#') + "}";
                        }

                        enteredQuantity = string.Format(formatString, parsedQuantity);
                        OnPropertyChanged(enteredQuantity);
                    }
                }
            }
        }

For the above test, the format string is {0:0.##} and decimal places are 2. I am trying to restrict the value in the Binding property. However, this does not reflect on the front end. The frontend will show any decimal places like in the picture below. Does anybody have an idea how to solve this?

Sample screenshot

Has

1 Answers

Use behavior to achieve this

Xaml Code

...
xmlns:local="clr-namespace:DummyTestApp"
...
<Entry HorizontalOptions="FillAndExpand" VerticalOptions="CenterAndExpand">
     <Entry.Behaviors>
            <local:LengthValidateBehavior MaxLength="7"/>
     </Entry.Behaviors>
</Entry>

Behavior Class

public class LengthValidateBehavior : Behavior<Entry>
    {
        public static BindableProperty MaxLengthProperty = BindableProperty.Create(nameof(MaxLength), typeof(int), typeof(LengthValidateBehavior), 5/* default value*/);

        public int MaxLength
        {
            get
            {
                return (int)GetValue(MaxLengthProperty);
            }
            set
            {
                SetValue(MaxLengthProperty, value);
            }
        }


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

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

        void OnEntryTextChanged(object sender, TextChangedEventArgs args)
        {
            if (sender is Entry entry)
            {
                if (args.NewTextValue.Length > MaxLength)// write your logic here
                {
                    entry.Text = args.OldTextValue;
                }
            }
        }
    }

Similarly use your own logic to restrict the entry as per your own requirements.

Related