Cosmin
Cosmin

Reputation: 585

Value Converter does not apply the desired string format

I have been trying to implement a simple value converter I just can't figure out why the StringFormat is not being applied. The positive values turn green and the negatives red but instead of getting the desired result (+15.74), I end up with: 15.74747474.

How can I get this to work? Can someone please give me an idea of what I need to change?

XAML

<Window.Resources>

    <local:PositiveConverter x:Key="PositiveConverter"/>

    <Style TargetType="TextBlock" x:Key="NumericTextBlock">
        <Style.Triggers>
            <DataTrigger Binding="{Binding Text, RelativeSource={RelativeSource Self}, Converter={StaticResource PositiveConverter}}" Value="True">
                <Setter Property="Foreground" Value="Green"/>
                <Setter Property="Text" Value="{Binding StringFormat='({0:+0.0})'}"/>
            </DataTrigger>

            <DataTrigger Binding="{Binding Text, RelativeSource={RelativeSource Self}, Converter={StaticResource PositiveConverter}}" Value="False">
                <Setter Property="Foreground" Value="Red"/>
                <Setter Property="Text" Value="{Binding StringFormat='({0:-0.0})'}"/>
            </DataTrigger>
        </Style.Triggers>
    </Style>

</Window.Resources>

    <Grid>
        <StackPanel>
            <TextBlock Text="{Binding ActualValue}" Style="{StaticResource NumericTextBlock}"/>
        </StackPanel>   
    </Grid>

ViewModel

namespace My.ViewModel
{
public class LocationViewModel : UserControl, INotifyPropertyChanged
{
public MyViewModel()
{
        SetActualValue();
}

public DateTime mDate = DateTime.Now;
public DateTime MDate
{  
get { return mDate; }
set
    {
        if (value == mDate)
        {
            return;
        }
        else
        {
            mDate = value;
            OnPropertyChanged("MDate");
            SetActualValue();
        }

    }

}

double _actualValue;
public double ActualValue
{
    get { return _actualValue; }
    set
    {
    _actualValue = value;
    OnPropertyChanged("ActualValue");
    }
}

ValueConverter

public class PositiveConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        var number = 0.0;
        var isNumber = double.TryParse(value.ToString(), out number);

        return isNumber && number >= 0.0;
    }

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

Upvotes: 1

Views: 532

Answers (1)

Clemens
Clemens

Reputation: 128061

Setting

Text="{Binding ActualValue}"

directly on the TextBlock has higher value precedence than a Style Setter like

<Setter Property="Text" Value="{Binding StringFormat='({0:+0.0})'}"/>

So the Bindings from the Setter will never be applied. They are also wrongly written, because they miss the property path ActualValue.

Your approach won't work. You should instead have DataTriggers with Bindings to the view model property like this:

<Style TargetType="TextBlock" x:Key="NumericTextBlock">
    <Setter Property="Text"
            Value="{Binding ActualValue, StringFormat='({0:+0.0})'}"/>

    <Style.Triggers>
        <DataTrigger Binding="{Binding ActualValue, Converter={StaticResource PositiveConverter}}"
                     Value="True">
            <Setter Property="Foreground" Value="Green"/>
            <Setter Property="Text"
                    Value="{Binding ActualValue, StringFormat='({0:+0.0})'}"/>
        </DataTrigger>

        <DataTrigger Binding="{Binding ActualValue, Converter={StaticResource PositiveConverter}}"
                     Value="False">
            <Setter Property="Foreground" Value="Red"/>
            <Setter Property="Text"
                    Value="{Binding ActualValue, StringFormat='({0:-0.0})'}"/>
        </DataTrigger>
    </Style.Triggers>
</Style>

and remove Text="{Binding ActualValue}" from the TextBlock.

Upvotes: 3

Related Questions