1

When i bind an object to a WPF control i want to display properties to different levels of precision depending on the unit system being used. For example i have a property IsMetric if the value is true i want to display the values with one decimal place if it is false then three decimal places. Currently I am adding a static resource string which is added to resources in the constructor before the call to InitialiseComponent() like this:

public RoomDisplay(Room room)
{
    string format = room.IsMetric ? "{0:0.0}" : "{0:0.000}";
    this.Resources.Add("format", format);
    InitializeComponent();
    this.DataContext = room;
}

Then the Xaml looks like this:

<TextBlock Grid.Row="0" Grid.Column="1" Text="{Binding Path=Breadth, StringFormat={StaticResource ResourceKey=format}}" TextAlignment="Right" />

This has worked upto now. However this approach falls down with embedded controls, that and i've never been happy with the approach.

I have investigated DataTriggers, something along the lines of:

<DataTrigger Binding="{Binding IsMetric}" Value="true">
    <Setter Property="Text" Value="{Binding Breadth, StringFormat=F1}"/>
</DataTrigger>
<DataTrigger Binding="{Binding IsMetric}" Value="false">
    <Setter Property="Text" Value="{Binding Breadth, StringFormat=F3}"/>
</DataTrigger>

However this is a pain to add to all the textblocks. Ideally i would like to put this into a style but i cant figure out a way of just setting the StringFormat without the text value.

The other option is to have a format property in the object and bind the StringFormat to that but i would prefer to stay away from this. Any Ideas? Thanks.

Cadair Idris
  • 587
  • 1
  • 9
  • 20

1 Answers1

0

Really, I think the simplest thing would be to have in Room class a property BreadthString, as long as you remember to sent the correct notifications on the appropriate setters.

class Room {
    private double _breadth;
    public Breadth {
        get { return _breadth; }
        set { _breadth = value; Raise("Breadth"); Raise("BreadthString"); }
    }

    private bool _isMetric;
    public bool IsMetric {
        get { return _isMetric; }
        set { _isMetric = value; Raise("IsMetric"); Raise("BreadthString"); }
    }

    public string BreathString {
        get { return Breadth.ToString( IsMetric ? "0.0" : "0.000" ); }
    }
}

You suggested to have a 'format' property in Room - I don't think it will work because StringFormat isn't a dependency property in a dependency object (I could be wrong here), but there are many other ways. For example, you could have a customer convertor (especially, if there is more than the Breadth property that has to be presented). Or, you could have a custom control derived from TextBlock. Or you could have two DataTemplates for and a TemplateTemplateSelector. Or you could have a ControlTemplate.

Uri London
  • 10,631
  • 5
  • 51
  • 81
  • "I don't think it will work because StringFormat isn't a dependency property in a dependency object" - You were right about this – Cadair Idris Mar 19 '12 at 11:04
  • I'm not having much sucess with this. I have looked at most of your suggestions without sucess, currently i'm trying teh converter approach here http://stackoverflow.com/questions/9982117/ivalueconverter-with-bound-dependency-properties – Cadair Idris Apr 02 '12 at 19:01