简体   繁体   English

如何以用户选择的单位显示温度

[英]How to display temperature in user chosen units

I have a WPF application that saves user defined temperature values in Celsius in the model.我有一个 WPF 应用程序,可以在模型中以摄氏温度保存用户定义的温度值。 These are entered in TextBoxes with numeric masks, which are bound to integer properties on the VM.这些是在带有数字掩码的文本框中输入的,这些掩码绑定到 VM 上的整数属性。

I would like to allow the user to be able to enter the temperature in either Celsius or Fahrenheit.我想让用户能够输入摄氏或华氏温度。 This is controlled by a simple User setting.这是由一个简单的用户设置控制的。 The value must therefore also be displayed in the correct unit in the textbox.因此,该值也必须以正确的单位显示在文本框中。

I've tried using a converter, but I'm not having much success.我试过使用转换器,但没有取得太大的成功。 I can get the converter to work, but not how I want to.我可以让转换器工作,但不是我想要的。

When the UserControl loads, the value might need to be converted from Celsius to Fahrenheit.当 UserControl 加载时,值可能需要从摄氏度转换为华氏度。 I was able to get this working using this converter:我能够使用此转换器使其正常工作:

    public class CelciusToFahrenheit : IValueConverter
    {
        /// <summary>
        /// Converts from Celsius to Fahrenheit if required by user settings
        /// </summary>
        /// <param name="value"></param>
        /// <param name="targetType"></param>
        /// <param name="parameter"></param>
        /// <param name="culture"></param>
        /// <returns></returns>
        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {
            double returnValue = System.Convert.ToInt32(value);

            if (Settings.Default.FahrenheitFlag)
            {
                returnValue = (returnValue * 1.8) + 32;
            }

            return Math.Floor(returnValue);
        }

        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
        {
            int returnValue = System.Convert.ToInt32(value);

            if (Settings.Default.FahrenheitFlag)
            {
                returnValue = System.Convert.ToInt32((returnValue - 32) / 1.8);
            }

            return returnValue;
        }
    }

The problem here is that this also converts the value when the user is typing the value in. This means that if you try to type 66, you end up with 77 due to the rounding error.这里的问题是,当用户输入值时,这也会转换值。这意味着如果您尝试输入 66,由于舍入错误,最终会得到 77。

Has anyone done this before?以前有人这样做过吗? I'm sure it's possible, but I've been banging my head against this for a while now.我敢肯定这是可能的,但我一直在反对这个问题有一段时间了。

I would do the calculation in a view model that can be bound to two text boxes.我会在可以绑定到两个文本框的视图模型中进行计算。 One for Celsius, one for Fahrenheit.一个是摄氏度,一个是华氏度。 If the user enters text in the Celsius text box, the Fahrenheit value is calculated and inserted into the Fahrenheit text box and vice versa.如果用户在摄氏度文本框中输入文本,则计算华氏度值并将其插入到华氏度文本框中,反之亦然。 No need to change a setting for this.无需为此更改设置。

public class TemperatureViewModel: INotifyPropertyChanged
{
    private double _celsius;
    public double Celsius
    {
        get { return _celsius; }
        set {
            if (value != _celsius) {
                _celsius = value;
                _fahrenheit = Math.Round(1.8 * value + 32.0, 2);
                OnPropertyChanged(nameof(Celsius));
                OnPropertyChanged(nameof(Fahrenheit));
            }
        }
    }

    private double _fahrenheit = 32.0;
    public double Fahrenheit
    {
        get { return _fahrenheit; }
        set {
            if (value != _fahrenheit) {
                _fahrenheit = value;
                _celsius = Math.Round((value - 32.0) / 1.8, 2);
                OnPropertyChanged(nameof(Fahrenheit));
                OnPropertyChanged(nameof(Celsius));
            }
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;

    private void OnPropertyChanged(string propertyName)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
}

Note that the VM implements INotifyPropertyChanged to tell the UI when the values change.请注意,VM 实现INotifyPropertyChanged以在值更改时通知 UI。 The effect is that the text boxes refresh automatically.效果是文本框自动刷新。 Note also the the property setters assign the calculated value to the backing field, not to the property, to avoid the two properties to update each other in a vicious cycle.另请注意,属性设置器将计算出的值分配给支持字段,而不是属性,以避免这两个属性在恶性循环中相互更新。

My implementation rounds the calculated temperatures to 2 fractional digits.我的实现将计算出的温度四舍五入到 2 个小数位。 But you can change this of course.但你当然可以改变这一点。

I don't believe this is where you should be doing your conversion.我不相信这是您应该进行转换的地方。 Your Model has a temperature property, which as you say is always stored as Celsius.您的模型具有温度属性,正如您所说,它始终存储为摄氏度。 And that's the way it should stay.这就是它应该保持的方式。

There are no need for value converters here, but probably want to move this calculation in to your ViewModel, and have the get and set properties determine what conversion has to happen based on the user settings, and avoid the value-converter all together.这里不需要值转换器,但可能希望将此计算移动到您的 ViewModel 中,并让getset属性根据用户设置确定必须发生的转换,并同时避免使用值转换器。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM