Home > Back-end >  Decimal First Price Entry
Decimal First Price Entry

Time:11-02


is there a way to achieve a PayPal like 'decimal-first' entry in Xamarin Forms?

example from PayPal

I hope the screenshot is self explanatory. I basically want an instantaneous division of the input by 100. For an input of e.g. 3,85 I want it shown as
0,03
0,38
3,85
Is there a good way to implement this in Xamarin Forms?
Tanks in advance

CodePudding user response:

This can be achieved by TextChanged event. Here's the code below for your reference:

Xaml:

<Entry                 
    Keyboard="Numeric"
    TextChanged="Entry_TextChanged"
  />

Code behind:

   private void Entry_TextChanged(object sender, TextChangedEventArgs e) 
        {
            

            var entry = (Entry)sender;
            var amt = e.NewTextValue.Replace("$", "");


            if (decimal.TryParse(amt, out decimal num))
            {
                // Init our number
                if (string.IsNullOrEmpty(e.OldTextValue))
                {
                    num = num / 100;
                }

                // Shift decimal to right if added a decimal digit
                else if (num.DecimalDigits() > 2 && !e.IsDeletion())
                {
                    num = num * 10;
                }

                // Shift decimal to left if deleted a decimal digit
                else if (num.DecimalDigits() < 2 && e.IsDeletion())
                {
                    num = num / 10;
                }

                entry.Text = num.ToString("C");
            }

            else
            {
                entry.Text = e.OldTextValue;
            }
        }
    }


    public static class ExtensionMethods
    {
        public static int DecimalDigits(this decimal n)
        {
            return n.ToString(System.Globalization.CultureInfo.InvariantCulture)

                    .SkipWhile(c => c != '.')

                    .Skip(1)

                    .Count();
        }

        public static bool IsDeletion(this TextChangedEventArgs e)
        {
            return !string.IsNullOrEmpty(e.OldTextValue) && e.OldTextValue.Length > e.NewTextValue.Length;
        }

    }


Reference link.

CodePudding user response:

I've been thinking about your question and got something you may want to. Try to bind your textBox with property Text="{Binding InputValue}. Then implement INotifyPropertyChanged interface by typing : INotifyPropertyChanged to your main class.

Create public event PropertyChangedEventHandler named PropertyChanged and add required:

private void OnPropertyChanged(string propertyName)
{
  PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}

Don't forget to set property, by typing InputValue = 0.00M add DataContext = this below InitializeComponent(); too.

It's very important to create fullprop like this:

private decimal inputValue;

public decimal InputValue
{
  get { return inputValue; }
  set
  {
    inputValue = value;
    OnPropertyChanged("InputValue");
  }
}

Now you have to set your textBox to be ReadOnly and add KeyDown event:

private void InputPriceTextBox_KeyDown(object sender, KeyEventArgs e)
{
  int num = 0;
  string stringVal = e.Key.ToString();

  if (stringVal.Length > 1)
  {
    if (stringVal.Contains("NumPad"))
    {
      num = Convert.ToInt32(stringVal.Substring(6));
    }
    else if (stringVal.Contains("D"))
    {
      num = Convert.ToInt32(stringVal.Substring(1));
    }
    else
    {
      return;
    }

    if (InputValue == 0.00M)
    {
      InputValue = 0.00M   (decimal)num / 100;
    }
    else
    {
      InputValue *= 10;
      InputValue  = (decimal)num / 100;
    }
  }
}

It works for me, try it yourself!

  • Related