我正在利用绑定到数据对象的 DataGridTextColumn 来显示应用程序中的各种测量值。我正在尝试实现一个允许以不同单位显示测量值的功能,并认为绑定中的转换器可能是我的最佳选择。
这适用于大多数应用程序,但我在 DataGrid 中有另一个字段,用户可以在其中编辑字段的值。在这种情况下,我有一个双向数据绑定,它将用户输入的值(比如说华氏度)转换回数据对象的默认单位(摄氏度)。
我希望转换器从数据对象中检索摄氏度的值,进行转换,然后将此值(以华氏度为单位)发送到 DataGridTextColumn。但是,在数据对象上设置值并通知 PropertyChanged 后,不会调用该属性的“get”方法。相反,Convert 似乎是从 DataGridTextColumn 获取用户输入的值(以华氏度为单位)。
这是正常行为吗?如果是这样,有没有办法强制 Convert 始终返回数据对象的值?
一些片段可以提供帮助:
<Window.Resources>
<myProject:ConvertMetricValuesToEnglish x:Key="ValueMToE" />
</Window.Resources>
.
.
.
<DataGridTextColumn x:Name="maxCol" Header="Maximum" Width="100">
<DataGridTextColumn.Binding>
<MultiBinding Mode="TwoWay" StringFormat='0.#####' Converter="{StaticResource ValueMToE}" >
<Binding Path="UserMax" Mode="TwoWay" />
<Binding Path="Unit" Mode="OneWay" />
</MultiBinding>
</DataGridTextColumn.Binding>
</DataGridTextColumn>
转换器方法:
public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
{
if (values.Length != 2)
{
return null;
}
if (values[0].GetType() != typeof(double) || values[1].GetType() != typeof(string))
{
return values[0];
}
double d = (double)values[0];
string s = (string)values[1];
return ConvertValueToEnglish(d, s);
}
public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
{
return new object[] { StringToDouble((string)value), Binding.DoNothing };
}
由于 ConvertBack 中可用的信息有限,我在 setter 中进行了“ConvertBack”转换:
private double? _userMax;
public double UserMax
{
get
{
if (_userMax == null)
{
_userMax = Max;
}
return (double)_userMax;
}
set
{
if (Metric)
{
if (value == _userMax)
{
return;
}
_userMax = value;
}
else
{
double num = ConvertValueToMetric(value, _unit);
if (num == _userMax)
{
return;
}
_userMax = num;
}
OnPropertyChanged("UserMax");
}
}
编辑:这是一个演示问题的示例项目的链接。左列是用户可编辑的,表示用户查看/编辑的数据。右列显示用户进行更改时实际存储的基础值(此值不应更改)。
如果您修改左列中的值,并在同一行中使用“制表符”或选择不同的列,您可以看到值与您输入的值不同。但是当行失去焦点时它会变回来。通过设置断点,您可以看到当单元格本身失去焦点时,使用 DependencyProperty.UnsetValue 调用 Convert 方法,然后调用 Unit 的 get 方法,然后再次使用 DataGrid 中的值调用 Convert 方法。