Skip to content

Binding units to (WPF) controls #290

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

Closed
samirem opened this issue Sep 29, 2017 · 10 comments
Closed

Binding units to (WPF) controls #290

samirem opened this issue Sep 29, 2017 · 10 comments

Comments

@samirem
Copy link

samirem commented Sep 29, 2017

I use this library in a WPF application that I'm building.

A recurring problem is that I haven't found a good way to databind (two-way) Units to my controls.

I wonder how you guys usually solve this? #71 sounds like a promising solution

@angularsen
Copy link
Owner

angularsen commented Sep 29, 2017

Hi, I have not yet tried anything like this myself, sorry. Have you looked into using IValueConverter? This way you can convert between say "1 kg" in GUI and Mass in a view model property, or in the example of #71 you would have a numeric input and a unit dropdown in the UI bound to one double and one string property in the VM, and update the value if the unit is change by the user.

https://www.codeproject.com/Tips/868163/IValueConverter-Example-and-Usage-in-WPF

@JKSnd
Copy link
Contributor

JKSnd commented Sep 29, 2017

FWIW, we're using WPF and Caliburn.Micro's MVVM framework with Units.Net in our domain model and our view models.

Implementing IValueConverter is absolutely the way to go for a two way binding.

Just wanted to back up Mr Larsen on this one.

@samirem
Copy link
Author

samirem commented Sep 30, 2017

This sounds like a good solution!

However, I ran into the following problem: I want the Unit to work as an application-level userdefined setting, and the ConverterParameter cannot be bound to because it is not a Dependency Property.

@JKSnd how would you solve this?

@penenkel
Copy link
Contributor

@samirem I ran into this precise issue not too long ago. My first approach was to treat the unit conversion as a concern of the view, as it is basically just a rendering detail. As such I implemented an IValueConverter an ran into the precise problem you described: ConverterParameter is not a Dependency Property and as such not blindable. To get around that you can use an IMultiValueConverter with a MultiBinding which allows you to pass the desired unit as a second binding. This works great until you try to implement the backwards conversion, at which point you will realize that you have no way to access the unit used in the forward conversion. Which is due to the fact that IMultiValueConverters are n->1 functions which means that the backward conversion must be 1->n which is impossible to do if not all information is included in that 1. For the specific case of converting units to and from the view the IMultiValueConverter approach will only work if you either only need OneWay conversion or include the unit abbreviations in your display, only then can you parse both the quantity and unit from the string for the backward conversion.

I ended up putting all conversion and rendering (by which I mean converting the numerical value and converting to string) into the view model and not using any converter.

@samirem
Copy link
Author

samirem commented Oct 2, 2017

@penenkel Thanks for your response! I also stumpled upon the problem you describe with IMultiValueConverter. It seems like we have been trying the exact same things 😄.

After some more research into this topic I found the following "hack": https://stackoverflow.com/a/13778519/4351604

Using that approach, I was able to define my unit as a Dependency Property in the converter (IValueConverter), and bind to that Dependency Property.

I hope that this trick may help you or someone else having this issue.

@JKSnd
Copy link
Contributor

JKSnd commented Oct 2, 2017

Nice one, @penenkel. Personally, I'd lean toward the view-model hold onto the unit information and allowing my mapping layer to handle converting between the view-model's units and the model's units rather than using an esoteric solution to make IValueConverters work.

As far as making those units user-settable and system wide, I'm sure you've already discovered the unit structs' ToStringDefaultUnit setters? You could build a little wrapper from them to detect changes and notify view models across your system, even.

@myarichuk
Copy link

myarichuk commented Oct 3, 2017

In my (pet) project, using IValueConverters for databanding works well.
First, I define centralized configuration class where I store currently selected units per each type --> https://github.com/myarichuk/Sharp.Ballistics/blob/master/Sharp.Ballistics.Calculator/Models/ConfigurationModel.cs

Then I use instances of FieldValueConverter for binding units.
https://github.com/myarichuk/Sharp.Ballistics/blob/master/Sharp.Ballistics.Calculator/Converters/FieldValueConverter.cs

@angularsen
Copy link
Owner

Should I close this or are you still discussing this topic?

@samirem
Copy link
Author

samirem commented Oct 13, 2017

I believe I got my question answered. Feel free to close it.

Thanks everyone for your helpful answers.

@angularsen
Copy link
Owner

Great :-)

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

5 participants