【发布时间】:2011-07-06 07:17:22
【问题描述】:
确切的问题是——为什么使用 Convert 而不是 ConvertBack,为什么这里首先需要 ConvertBack?
问题
以下是我的问题示例,我试图简化事情。这是普通的 WPF,没有 3rd 方库,问题本身是经典的主从细节,有点扭曲。
我有列表框(城市列表)和数据网格(列出我所有的朋友+电话)。当我选择列表框时,数据网格应该刷新并显示来自所选城市的人。数据网格如下所示:
Name | Phone | PhoneType
Mark | 76447 | cellphone
...
这里的关键问题是 PhoneType 列。每个单元格应该是一个组合框,其中填充了预定义的电话类型(从数据库中获取)。扭曲在于 db 结构。是这样的:
typeID | PhoneType | PhoneDescription
1 | cellphone | NULL
2 | neighbour | call only in case of emergency
在我的数据网格组合框中,PhoneType 应该显示BUT,如果 PhoneDescription 存在,则应该使用它而不是普通的 PhoneType。
问题结束。你和我一起吗?
实施
为了在数据网格中有组合框,我必须使用带有组合框的模板列,而不是组合框数据网格列(原因如下:WPF Datagrid ComboBox DataBinding)。所以这是我的组合框:
<ComboBox ItemsSource="{Binding Path=PhoneTypesList,
RelativeSource={RelativeSource AncestorType={x:Type Window}}}"
好的,这里(上图)我定义了应该在 Combobox 下拉列表中列出的内容。 PhoneType 记录列表(在数据库意义上)。
SelectedValuePath="typeID"
SelectedValue="{Binding Path=typeID}">
Combobox 应该知道我朋友的电话类型的当前值,所以这里(上图)是我绑定这些值的方式——一方面我设置了 PhoneType 记录中的 typeID 应该用于匹配,另一方面手我设置应该使用来自 Friend 记录的 typeID。这样,WPF 就知道应该将哪个电话类型记录用作当前值。
(如果您不是 100% 熟悉此绑定,这里有一个很好的解释: Difference between SelectedItem, SelectedValue and SelectedValuePath)
顺便说一句。 typeID 使用了两次,因为通常我更喜欢在数据库中的相关字段(外键字段)中使用完全相同的名称。
我有列表,我已经完成了匹配,现在——为了显示,我不能只使用 DisplayMemberPath,因为我需要更动态的东西。
<ComboBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Converter={StaticResource PhoneTypeConverter}}"/>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
所以要显示 PhoneType,我会获取整个记录并选择适当的字符串。
[ValueConversion(typeof(PhoneTypeRecord), typeof(string))]
public class PhoneTypeConverter : IValueConverter
{
public object Convert(object value, Type targetType,
object parameter, CultureInfo culture)
{
if (value == null)
return null;
var record = ((PhoneTypeRecord)value); // crash!
return record.PhoneDescription ?? record.PhoneType;
}
// we don't do any conversion back
public object ConvertBack(object value, Type targetType,
object parameter, CultureInfo culture)
{
return null;
}
}
错误
我编译整个应用程序,我运行它,我点击任何城市。它按预期工作,很棒。
然后我点击另一个城市。应用程序思考了一下,然后在刷新城市列表框或数据网格之前,它崩溃并出现异常(参见上面的标记行)说:
无法转换类型的对象 'System.String' 键入 'MyBuilderApp.PhoneTypeRecord'。
我不知道发生了什么。为什么字符串被传递给转换???它看起来更像是 ConvertBack。
【问题讨论】:
-
在你的转换器中设置一个断点,看看给出的是什么字符串。这可能有助于您识别问题。
-
@Rachel,你在 VS 中强制断点异常 ;-) 空(非空)字符串。
标签: c# wpf data-binding ivalueconverter