无法在WPF中使用IMultiValueConverter来允许度量或英制输入

时间:2010-07-02 22:29:57

标签: c# wpf binding

我想创建一个收集设备测量值的C#WPF表单,但有些用户会尝试使用英尺和英寸进行测量,而其他(较年轻)用户则使用公制进行测量。数据库以米为单位存储所有内容,我认为这是使用 IMultiValueConverter 的理想场所。

每个表单都有一个名为 UseImperialMeasurements DependencyProperty ,用于存储用户首选项,我将此值传递给 Convert 函数以及实际以米为单位的测量到目前为止,代码如下所示:

<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...
    }
}

这适用于显示测量值,但是将它们作为公制或英制的输入一直存在问题,因为我无法在 ConvertBack中看到 UseImperialMeasurements 属性的绑定值方法。因此,我不仅无法猜测用户是否在未指定单位时输入英尺或米,但我无法知道要返回的布尔值,以便用户设置首选项不会更改。

是否可以将 UseImperialMeasurements 的值传递给 ConvertBack 函数?

2 个答案:

答案 0 :(得分:1)

您的ConvertBack方法应解析字符串中的单位,设置 UseImperialMeasurements属性(通过返回数组中的秒项)。

答案 1 :(得分:0)

将UseImperialMeasurements值存储为应用程序设置(或任何您想要的地方,实际上,但用例有利于应用程序范围的用户设置)。双击Visual Studio中项目树中的“属性”项,即可实现此目的。在那里,只需点击“设置”标签,然后将“UseImperialMeasurements”添加为bool,作用域User,并设置默认值。

然后,在代码中的任何位置,使用Properties.Settings.Default.UseImperialMeasurements属性访问和更改值。

如果您记得在关闭表单或应用程序之前调用Properties.Settings.Default.Save(),则设置将为“Stick”。

然后,在XAML中,您将使用此绑定访问该设置:

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

或者,忘掉转换器。将此功能烘焙到ViewModel中,并将UseImperialMeasurements值存储为应用程序设置(或者您想要的任何地方,实际上,但用例有利于用户设置)

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;
}