我正在利用绑定到数据对象的DataGridTextColumn来显示应用程序中的各种度量。我正在尝试实现一个允许测量以不同单位显示的功能,并认为绑定中的转换器可能是我的最佳选择。
这适用于大多数应用程序,但我在DataGrid中有另一个字段,用户可以在其中编辑字段的值。在这种情况下,我有一个双向数据绑定,将来自用户的输入值(让我们说在华氏度)转换回数据对象的默认单位(摄氏度)。
我希望Converter从数据对象中检索Celcius中的值,进行转换,然后将此值(以华氏度)发送到DataGridTextColumn。但是,在数据对象上设置值并通知PropertyChanged后,不会调用该属性的“get”方法。相反,转换似乎是从DataGridTextColumn获取用户输入的值(华氏温度)。
这是正常的行为,如果是这样,有没有办法强制转换为总是返回数据对象的值?
一些要提供帮助的摘要:
<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 };
}
我在setter中进行'ConvertBack'转换,因为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方法。
答案 0 :(得分:2)
我能够自己解决问题。问题是在DataGrid中的整行失去焦点之前,源数据对象没有被更新。为了解决这个问题,我将一个TextBox作为ControlTemplate应用于单元格,并设置一个事件,以便在TextBox失去焦点时触发UpdateSource。
XAML:
<DataGridTextColumn x:Name="maxCol" Header="Maximum" Width="100">
<DataGridTextColumn.CellStyle>
<Style TargetType="DataGridCell">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate>
<TextBox LostFocus="TextBlock_LostFocus">
<TextBox.Text>
<MultiBinding StringFormat='0.#####' Converter="{StaticResource ValueMToE}" UpdateSourceTrigger="Explicit">
<Binding Path="UserMax" Mode="TwoWay" />
<Binding Path="Unit" Mode="OneWay" />
</MultiBinding>
</TextBox.Text>
</TextBox>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</DataGridTextColumn.CellStyle>
</DataGridTextColumn>
事件处理程序:
private void TextBlock_LostFocus(object sender, RoutedEventArgs e)
{
TextBox b = sender as TextBox;
if (b == null)
{
return;
}
MultiBindingExpression mb = BindingOperations.GetMultiBindingExpression(b, TextBox.TextProperty);
mb.UpdateSource();
}