Cannot use IMultiValueConverter in WPF to provide metric or imperial input

I would like to create a C # WPF form that collects equipment measurements, but some users insert notes and inches for measurements, while other (younger) users do everything in the metric. The database stores everything in meters, and I thought it was the perfect place to use IMultiValueConverter.

Each form has a DependencyProperty called UseImperialMeasurements, which stores user preferences, and pass that value to the Convert function along with the actual measurement in meters. The code looks like this:

<Label>Length:</Label> <TextBox> <TextBox.Text> <MultiBinding Converter="{StaticResource DistanceStringConverter}" Mode="TwoWay"> <Binding Path="Length" /> <Binding ElementName="ThisControl" Path="UseImperialMeasurements" /> </MultiBinding> </TextBox.Text> </TextBox> public class DistanceStringConverter : IMultiValueConverter { public object Convert(object[] values, Type targetType, object parameter, System.Globalization.CultureInfo culture) { if (values.Length != 2 || !(values[0] is Double) || !(values[1] is Boolean)) return "ERROR"; Double measurement = (Double)values[0]; // Always in meters Boolean useImperial = (Boolean)values[1]; string unit; if (useImperial == true) { double feet, inches; inches = (measurement * 100) / 2.54; feet = Math.Floor(inches / 12); inches = inches % 12; var replacements = new object[4]; replacements[0] = feet.ToString("#,0"); replacements[1] = "'"; replacements[2] = inches.ToString("0"); replacements[3] = "\""; // Display like 12'4" return string.Format("{0}{1}{2}{3}", replacements); } else { // Display like 5,987.97m return string.Format("{0}{1}", measurement.ToString("#,0.##"), m); } } public object[] ConvertBack(object value, Type[] targetTypes, object parameter, System.Globalization.CultureInfo culture) { // ToDo: Figure out if imperial or metric measurements are prefered... } } 

This works well for displaying dimensions, but using them as input for both metric and imperial was problematic since I cannot see the associated value of the UseImperialMeasurements property in the ConvertBack method. Thus, I can not only guess if the user enters legs or meters when no units are specified, but I have no way to find out which logical value needs to be returned so that the user settings do not change.

Can I pass the value of UseImperialMeasurements to the ConvertBack function?

+4
source share
2 answers

Save the value of UseImperialMeasurements as the application parameter (or anywhere you want, actually, but the use case supports customizing the application). You get to this by double-clicking the Properties item in the Project tree in Visual Studio. There just go to the Settings tab and add " UseImperialMeasurements " as a bool , the User area and set the default value.

Then, wherever you are in your code, access and change the value using the Properties.Settings.Default.UseImperialMeasurements property.

If you forget to call Properties.Settings.Default.Save () before closing the form or application, the setting will be "Stick".

In XAML, you will access the settings using this binding:

 {Binding Source={x:Static my:Settings.Default},Path=UseImperialMeasurements} 

Or, forget the Converters. Highlight this functionality in the ViewModel and save the UseImperialMeasurements value as the application parameter (or anywhere you want, really, but the use case supports customization)

 public class BackingDataClass { public double LengthAlwaysMetric { get; set; } } public class BackingDataClassViewModel : INotifyPropertyChanged { public BackingDataClass Data { get; set; } public double Length { get { if (Properties.Settings.Default.UseImperialMeasurements == true) { return ConvertToImperial(Data.LengthAlwaysMetric); } else { return _lengthAlwaysMetric; } } set { if (Properties.Settings.Default.UseImperialMeasurements == true) { Data.LengthAlwaysMetric = ConvertToMetric(value); } else { Data.LengthAlwaysMetric = value; } PropertyChanged(this, new PropertyChangedEventArgs("Length")); } } public event PropertyChangedEventHandler PropertyChanged; } 
0
source

Your ConvertBack method should parse the units from the string and set the UseImperialMeasurements property (through the seconds element in the returned array).

+1
source

Source: https://habr.com/ru/post/1314586/


All Articles