Morothar
Topic Author
Posts: 3
Joined: 09 Jun 2014, 11:13

System.Double and System.Decimal in Binding

11 Aug 2015, 02:51

Hi,

I'm working on an non-game application with Unity. I tried to bind some UI elements to decimal values. I found out that double and decimal values aren't supported, at least when using ValueConverters that take decimals in Convert and return decimals in ConvertBack. Are there any plans to support these value types?

Does anyone know of a good workaround apart from using additional floats just for my UI? In my case that might work, but I can think of use cases where a user would type in a decimal into a textbox, essentially losing important precision if flots are used internally.

Morothar
 
User avatar
sfernandez
Site Admin
Posts: 1911
Joined: 22 Dec 2011, 19:20

Re: System.Double and System.Decimal in Binding

12 Aug 2015, 14:29

Hi,

You are right, double and decimal values are not working when returned in ValueConverters, could you please report this issue in our bugtracker? We want to support all basic types defined in C#.

Right now the only workaround is to cast the double/decimal value to float before returning it from your ValueConverter ConvertBack. You won't need an extra float property for binding, for example:
public class FloatConverter : Noesis.IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        if (value is float && targetType == typeof(string))
        {
            float f = (float)value;
            return f.ToString();
        }

        throw new Exception("Convert");
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        if (value is string && targetType == typeof(float))
        {
            string s = (string)value;
            return Single.Parse(s);
        }

        throw new Exception("ConvertBack");
    }
}

public class DoubleConverter: Noesis.IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        // Double internally treated as float, so a float value will be received
        if (value is float && targetType == typeof(string))
        {
            float f = (float)value;
            return f.ToString();
        }

        throw new Exception("Convert");
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        if (value is string && targetType == typeof(float))
        {
            string s = (string)value;
            // Double internally treated as float, so a float should be returned
            return (float)Double.Parse(s);
        }

        throw new Exception("ConvertBack");
    }
}

public class DecimalConverter: Noesis.IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        // Decimal internally treated as float, so a float value will be received
        if (value is float && targetType == typeof(string))
        {
            float f = (float)value;
            return f.ToString();
        }

        throw new Exception("Convert");
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        if (value is string && targetType == typeof(float))
        {
            string s = (string)value;
            // Decimal internally treated as float, so a float should be returned
            return (float)Decimal.Parse(s);
        }

        throw new Exception("ConvertBack");
    }
}

public class Context: System.ComponentModel.INotifyPropertyChanged
{
    float _f;
    public float FloatProp
    {
        get { return _f; }
        set
        {
            if (_f == value) return; _f = value; OnPropertyChanged("FloatProp");
            Debug.Log("FloatProp = " + _f.ToString());
        }
    }

    double _d;
    public double DoubleProp
    {
        get { return _d; }
        set
        {
            if (_d == value) return; _d = value; OnPropertyChanged("DoubleProp");
            Debug.Log("DoubleProp = " + _d.ToString());
        }
    }

    decimal _m;
    public decimal DecimalProp
    {
        get { return _m; }
        set
        {
            if (_m == value) return; _m = value; OnPropertyChanged("DecimalProp");
            Debug.Log("DecimalProp = " + _m.ToString());
        }
    }

    public event System.ComponentModel.PropertyChangedEventHandler PropertyChanged;

    protected void OnPropertyChanged(string name)
    {
        System.ComponentModel.PropertyChangedEventHandler handler = PropertyChanged;
        if (handler != null)
        {
            handler(this, new System.ComponentModel.PropertyChangedEventArgs(name));
        }
    }
}

public class Test: MonoBehaviour
{
    void Start()
    {
        var gui = GetComponent<NoesisGUIPanel>();
        var content = gui.GetContent();
        content.DataContext = new Context { FloatProp = 1.2f, DoubleProp = 3.4, DecimalProp = 5.6m };
    }
}
<Grid
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
    <Grid.Resources>
        <FloatConverter x:Key="floatConverter"/>
        <DoubleConverter x:Key="doubleConverter"/>
        <DecimalConverter x:Key="decimalConverter"/>
    </Grid.Resources>
    <StackPanel HorizontalAlignment="Center" VerticalAlignment="Center" Background="WhiteSmoke">
        <StackPanel Orientation="Horizontal" Margin="2">
            <TextBlock Text="Float = " TextAlignment="Right" VerticalAlignment="Center" Width="100"/>
            <TextBox Text="{Binding FloatProp, Converter={StaticResource floatConverter}}" Width="150"/>
        </StackPanel>
        <StackPanel Orientation="Horizontal" Margin="2">
            <TextBlock Text="Double = " TextAlignment="Right" VerticalAlignment="Center" Width="100"/>
            <TextBox Text="{Binding DoubleProp, Converter={StaticResource doubleConverter}}" Width="150"/>
        </StackPanel>
        <StackPanel Orientation="Horizontal" Margin="2">
            <TextBlock Text="Decimal = " TextAlignment="Right" VerticalAlignment="Center" Width="100"/>
            <TextBox Text="{Binding DecimalProp, Converter={StaticResource decimalConverter}}" Width="150"/>
        </StackPanel>
    </StackPanel>
</Grid>
We internally treat double and decimal properties as float, so if you really need to keep the precision, please report another ticket about this in our bugtracker.

Thanks for your collaboration.

Who is online

Users browsing this forum: Google [Bot] and 1 guest