我想创建一个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函数中?
最佳答案
将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;
}