Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Best practices for working with dynamic units? #587

Closed
Mobz87 opened this issue Jan 24, 2019 · 10 comments
Closed

Best practices for working with dynamic units? #587

Mobz87 opened this issue Jan 24, 2019 · 10 comments

Comments

@Mobz87
Copy link

Mobz87 commented Jan 24, 2019

I'm working on a program where the customer wants to be able to change the 'default units'.

ex
In a Settings-tab:
Pressure (choose) Bar or Pascal.
If you select 'Bar' then all input and output are displayed in Bar.

Right now I have hard coded it like:

Pressure = Pressure.FromBars(Control.Value);

OutputBox = Pressure.ToUnit(PressureUnit.Bar).ToString();

What is Best practices for making dynamic units?

@tmilnthorp
Copy link
Collaborator

I would generally populate a combo box with the pressure units. I use a wrapper like so to store a string/value:

internal class ComboBoxItemWrapper<T>
{
	private T item;
	private readonly Func<ComboBoxItemWrapper<T>, string> toStringMethod;

	public ComboBoxItemWrapper( T item, string text )
	{
		this.item = item;
		this.toStringMethod = cbiw => text;
	}

	public ComboBoxItemWrapper( T item, Func<ComboBoxItemWrapper<T>, string> toStringMethod )
	{
		this.item = item;
		this.toStringMethod = toStringMethod;
	}

	public override bool Equals( object obj )
	{
		if( obj is T )
			return Item.Equals( obj );
		else
			return base.Equals( obj );
	}

	public T Item
	{
		get { return item; }
	}

	public override string ToString()
	{
		return toStringMethod( this );
	}
}

And populate a combo box like so:

foreach( PressureUnit unit in Enum.GetValues( typeof( PressureUnit ) ) )
{
	if( unit == PressureUnit.Undefined )
		continue;

	var comboBoxItem = new ComboBoxItemWrapper<PressureUnit>( unit, UnitAbbreviationsCache.Default.GetDefaultAbbreviation( unit ) );
	pressureChoiceComboBox.Items.Add( comboBoxItem );
}

Then you can switch like so:

var selectedPressureUnit = ( (ComboBoxItemWrapper<PressureUnit>)pressureChoiceComboBox.SelectedValue ).Item;
var pressure = Pressure.From( Control.Value, selectedPressureUnit );

@angularsen
Copy link
Owner

angularsen commented Jan 26, 2019

I think you should get far by using this:

  • Pressure.From(value, selectedUnit) for reading input values in the configured default unit
  • myPressure.ToUnit(selectedUnit).ToString() for showing the value and unit as a string
  • myPressure.As(selectedUnit) for showing the value in the default unit

@Mobz87
Copy link
Author

Mobz87 commented Jan 28, 2019

Thanks you two for your feedback!

If I make a new pressure unit:
Pressure _pressure = new Pressure((double)Control.Value, DefaultUnit);

And then change its unit:
_pressure.As(NewUnit);

Displaying it value:
Debug.Print(_pressure.Value);

The output is displayed as the DefaultUnit and not the NewUnit.
It is a mistake or have I misunderstod its functionality?

Also if I do:
Debug.Print(_pressure.Unit.ToString());

It prints it name: poundspersquareinch
And not its unit: Psi

Is there another way to display its units rather then its name?

@tmilnthorp
Copy link
Collaborator

_pressure.As(NewUnit); does not change the value of _pressure, it returns the converted pressure.

var converted = _pressure.As(NewUnit);
Debug.Print(converted.Value);

As for the unit, it's just an enum. In that case you're doing a .ToString on an enum.

To get the abbreviation, do the following:

UnitAbbreviationsCache.Default.GetDefaultAbbreviation(NewUnit)

@angularsen
Copy link
Owner

angularsen commented Jan 28, 2019

To be clear, converted here is double not Pressure.

double converted = _pressure.As(NewUnit);

To change the unit, use ToUnit().

Is it possible you simply want to do this?

string psiText = _pressure.ToUnit(PressureUnit.PoundForcePerSquareInch).ToString(); // "20 psi"

@angularsen
Copy link
Owner

@Mobz87 There is a pretty big PR #576 on the way to greatly improve working dynamically with units.

Please see the PR's updated README.

@MrFoged
Copy link

MrFoged commented Jan 29, 2019

To be clear, converted here is double not Pressure.

double converted = _pressure.As(NewUnit);

To change the unit, use ToUnit().

Is it possible you simply want to do this?

string psiText = _pressure.ToUnit(PressureUnit.PoundForcePerSquareInch).ToString(); // "20 psi"

I just want it without the 20 - so just the psi

Right now I can get the value + unit:
Ex 20 psi

Or I can get the value:
Ex 20

Or I can get the name:
PoundForcePerSquareInch (Name of enum)

Im just missing the unit in a string:
psi

@angularsen Looks great that you're already looking into improve working dynamically with units!

@angularsen
Copy link
Owner

Ah, then what Tristan proposed should work for you.

To get the abbreviation, do the following:

UnitAbbreviationsCache.Default.GetDefaultAbbreviation(PressureUnit.PoundForcePerSquareInch) // "psi"

@MrFoged
Copy link

MrFoged commented Jan 29, 2019

I posted from the the wrong account :-)
Thanks I just do that!

@angularsen
Copy link
Owner

Ok, I'm closing this issue. Just reopen if there is anything else.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants