.netxamldata-bindingmaui

.NET Maui XAML Data Binding Failures on Int32 & Doubles


I have a .NET MAUI app using databinding and trying to format values as currency in an Entry field. The property is a double and the binding does work however I get XAML Data Binding Failures. Normal string fields work fine, only when using Double and Int32 do I get these failures. Clearly a double cannot store characters like a dollar sign, comma, or period so the error in general makes sense, but I cannot figure out how to have onscreen formatting but only pass the value without formatting.

public class LeaseAgreement : Base
{
    public string Description { get; set; }
    public DateTime DateLeaseStarted { get; set; }
    public int TotalMonths { get; set; }
    public int AnnualMiles { get; set; }
    public **double ExcessPerMileAmount** { get; set; }
<Label Grid.Row="3" Grid.Column="0" Text="Excess Milage Charge" Style="{StaticResource FormLabel}" />
<Entry Grid.Row="3" Grid.Column="1" Text="{Binding **ExcessPerMileAmount**, StringFormat='{0:C2}'}" Style="{StaticResource FormEntry}" Keyboard="Numeric" />

I've tried databinding with StringFormat (as seen above). I have also tried Behaviors on the Entry field.

The numeric value is captured and the application fully works in Windows, iOS, and Android. However it throws a ton of XAML Data Binding Failures and is messy, especially if using generic exception monitoring.

Any suggestions are greatly appreciated!


Solution

  • Create a converter that can convert your currency type to a decimal value something similar to this:

    public class CurrencyConverter : IValueConverter
        {
            public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
            {
                return Decimal.Parse(value.ToString()).ToString("C");
            }
    
            public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
            {
                string valueFromString = Regex.Replace(value.ToString(), @"\D", "");
    
                if (valueFromString.Length <= 0)
                    return 0m;
    
                long valueLong;
                if (!long.TryParse(valueFromString, out valueLong))
                    return 0m;
    
                if (valueLong <= 0)
                    return 0m;
    
                return valueLong / 100m;
            }
        }
    

    Define the same in your resources an example of this is below:

      <ContentPage.Resources>
        <ResourceDictionary>
          <util:CurrencyConverter x:Key="currencyConverter" />
        </ResourceDictionary>
      </ContentPage.Resources>
    

    Use that in your text property

    Text="{Binding SomeProperty, Converter={StaticResource currencyConverter}}"
    

    And the property that you need to bind would be something like this:

        public decimal SomeProperty { get; set; }
    

    If needed you can make this an observable property

    This is based on the example I used back in the day for Xamarin forms which can be found here https://gist.github.com/alfeugds/786260ab70a49565070338052ceaee3e