JoeyD
JoeyD

Reputation: 743

Dynamic StringFormat on XAML TextBox via a property on the ViewModel

I have a XAML view with 10 TextBox bound to 10 properties on my ViewModel. Each of those properties on my ViewModel have a corresponding property to SignificantDigits value. IE PropertyA has a significant digit value of 2. PropertyB has a significant digit value of 4. Therefore within the UI i want to display PropertyA as 1.12 and PropertyB as 1.4312.

Is there a way using StringFormat to bind to the SignificantDigit value on the VM to limit the number of decimal places shown?

Example.

PropertyA = 1.231231;
PropertyB = 1.234234;

PropertyASignificantDigits = 2;
PropertyBSignificant Digits = 4;

<TextBox  Text="{Binding PropertyA, StringFormat={}{0:{PropertyASignificantDigits}}" TextAlignment="Center" />

The UI would then display 1.23 for PropertyA

Id prefer not to use a converter if i can manage it from within the xaml

Upvotes: 0

Views: 1363

Answers (2)

JoeyD
JoeyD

Reputation: 743

Thanks to Keithernet the answer for me was that you cannot do this within XAML directly and needed to use a converter. Using his answer, this is how my final converter looks

public class DecimalPlaceStringFormatConverter : IMultiValueConverter
    {
        public object Convert( object[] values, Type targetType, object parameter, CultureInfo culture )
        {
            if( !decimal.TryParse( values[ 0 ].ToString(), out decimal value ) )
                return values[ 0 ].ToString();

            if( !int.TryParse( values[ 1 ].ToString(), out int decimalPlaces ) )
                return value;

            if( values.Length == 2 )
                return string.Format( $"{{0:F{decimalPlaces}}}", value );
            else
                return value;
        }

        public object[] ConvertBack( object value, Type[] targetTypes, object parameter, CultureInfo culture )
        {
            throw new NotImplementedException();
        }
    }

Upvotes: 0

Keithernet
Keithernet

Reputation: 2509

You can accomplish this with a MultiBinding and a IMultiValueConverter.

The MultiBinding takes in your value and number of decimal places and then uses a custom multi value converter to do a string.Format on the value, returning the result.

Here is a simple example:

XAML

<TextBox>
    <TextBox.Text>
        <MultiBinding Converter="{StaticResource DecimalPlaceStringFormatConverter}">
            <Binding Path="PropertyAValue" />
            <Binding Path="PropertyADecimalPlaces" />
        </MultiBinding>
    </TextBox.Text>
</TextBox>

Converter

public class DecimalPlaceStringFormatConverter : IMultiValueConverter
{
    public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
    {
        string result = null;

        if (values.Length == 2 && values[0] is double value && values[1] is int decimalPlaces)
        {
            result = string.Format($"{{0:F{decimalPlaces}}}", value);
        }

        return result;
    }

    public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}

Upvotes: 1

Related Questions