dukesta3
dukesta3

Reputation: 137

Is there a clean way to handle unit (degrees, radians, etc.) conversions in a WPF application

I am working on a plug-in to a mapping application that has quite a few classes that have a ton of options for units. I feel like I have a pretty good handle on maintaining order within the model.For example, the Angle class has properties for Degrees and Radians and automatically updates each other. The Altitude class does the same thing for feet MSL, meters MSL, meters HAE, etc.

However, when I get into the WPF side, I would like to have any data entry points have a TextBox so that they can enter in values but also display the units. I am currently using Caliburn Micro to use composition and it has been a total game changer for me. In the past, I would have hacked together some sort of enum and mapped them to each individual viewmodel with potentially a lot of code duplication and definitely making the code brittle. I don't want to have some sort of SelectedUnit feature in the Model because I feel that a string representation of the units is only valuable to the view.

Any ideas to implement a clean mapping between a value and its units that will allow for composition?

Upvotes: 2

Views: 906

Answers (1)

Charleh
Charleh

Reputation: 14012

I'm not sure I fully understand what the C++ lib does and why you needed to wrap it, but if you have a base unit of measure somewhere, then it is pretty trivial to convert into another UOM using a relative value (exchange rate)

Doing so means that your model doesn't need to change and can expose a single property for the converted value and a single property for the base value. Changing the UOM would cause the converted UOM value to change

e.g.

class SomeModel 
{ 
    // You can assume that the base UOM has a conversion rate of 1
    UnitOfMeasure BaseUnitOfMeasure { get; }

    decimal BaseQuantity { get; }

    UnitOfMeasure UnitOfMeasure { get; set; }

    decimal Quantity { get { return UnitOfMeasure.Convert(BaseQuantity, BaseUnitOfMeasure); } }

   // or if you are assuming base UOM is conversion rate of 1 then you can just use
   // decimal Quantity { get { return UnitOfMeasure.Convert(BaseQuantity); } }
}

Then binding becomes simple:

<TextBox Text="{Binding Quantity, Mode=TwoWay}" /><TextBlock Text="{Binding UnitOfMeasure.Name}" />

Your view doesn't need to change to display a new unit of measure, you just assign a new UOM to the UnitOfMeasure property, and any subsequent calls to Quantity return the new converted rate.

Obviously I'm leaving out a fair bit of notification code but you can fill that in

Does this make things easier or have you already considered this?

I know that you don't want to 'pollute' your model with a UOM string, but the UOM is part of the model really. If not it's at least a ViewModel concern but I wouldn't bother changing your views to accommodate when you can do it quite efficiently without

Upvotes: 1

Related Questions