We are possibly about to introduce UnitsNet in our application for two reasons: Type safe computations and ability to switch between different unit systems (metric, imperial etc.) This means those types will be all over our application and also in our view models for presentation. And this is where it gets tricky. I would like the various quantities to be displayed more or less automatically in the GUI, solely by specifying the desired unit.
Since there will be a lot of those quantities it would be tiresome to always specify a type converter in the xaml file, and I'm not sure it would be possible to specify which unit to display at the same time.
So what would be a good approach to this? Writing your own user controls, using conversion attributes, or is there a better way?
UnitsNet
quantity classes (e.g. Length
, Mass
, etc) have a public static
ToStringDefaultUnit
property which you can set to whichever Unit
you want the quantity classes to be displayed as (ToString
) during runtime.
For example:
Length myLength = Length.FromMeters(1);
//default Length.ToStringDefaultUnit is LengthUnit.Meter
string display1 = myLength.ToString(); //1m
Length.ToStringDefaultUnit = LengthUnit.Centimeter;
string display2 = myLength.ToString(); //100cm
Length.ToStringDefaultUnit = LengthUnit.Foot;
string display3 = myLength.ToString(); //3.28ft
If you need different units per quantity then it would be a good idea to create new types to represent the difference. It would also be a good idea to copy how UnitsNet does the implementation to be consistent.
public struct ShortLength
{
private Length _internalLength;
public ShortLength(QuantityValue centimeters)
{
_internalLength = Length.FromCentimeters(centimeters);
}
public static ShortLength FromCentimeters(QuantityValue value)
{
return new ShortLength(value);
}
public static LengthUnit ToStringDefaultUnit { get; set; } = LengthUnit.Centimeter;
public override string ToString()
{
return ToString(ToStringDefaultUnit);
}
public string ToString(LengthUnit lengthUnit)
{
//just copy how UnitsNet implement ToString
}
}
One way to leverage the ToStringDefaultUnit
property is to have one class that will manage the conversion for the whole app. This way, your unit conversions will not be all over the place.
public static class AppUnitSystem
{
public static void ToMetric()
{
Length.ToStringDefaultUnit = LengthUnit.Meter;
ShortLength.ToStringDefaultUnit = LengthUnit.Centimeter;
Density.ToStringDefaultUnit = DensityUnit.KilogramPerCubicMeter;
//TODO: other quantities...
}
public static void ToImperial()
{
Length.ToStringDefaultUnit = LengthUnit.Foot;
ShortLength.ToStringDefaultUnit = LengthUnit.Inch;
Density.ToStringDefaultUnit = DensityUnit.PoundPerCubicFoot;
//TODO: other quantities...
}
}