为什么Convert方法用于在WPF组合框中转换一个值?

时间:2011-07-06 07:17:23

标签: c# wpf data-binding ivalueconverter

确切的问题是 - 为什么使用Convert而不是ConvertBack,为什么首先需要ConvertBack呢?

问题

下面是我的问题的例子,我试图简化一些事情。这是普通的WPF,没有第三方库,问题本身就是经典的主要细节,有点麻烦。

我有listbox(城市列表)和datagrid(列出我所有的朋友+电话)。当我选择列表框时,datagrid应刷新并显示所选城市的人员。 datagrid如下所示:

Name | Phone | PhoneType
Mark | 76447 | cellphone
...

这里的关键问题是PhoneType列。每个单元格应该是一个填充预定义手机类型的组合框(从数据库中获取)。而扭曲在于db结构。它是这样的:

typeID | PhoneType | PhoneDescription
1      | cellphone | NULL
2      | neighbour | call only in case of emergency

在我的数据网格组合框中,如果存在PhoneDescription,则应显示 PhoneType,应使用它而不是普通的PhoneType。

问题的结束。你和我在一起?

实施

为了在datagrid中使用combobox,我必须使用带有combobox的模板列,而不是使用combobox datagrid列(这就是为什么: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'。

有了这个,我不知道发生了什么。为什么字符串传递给Convert ???它看起来更像ConvertBack。

2 个答案:

答案 0 :(得分:1)

我认为在这种情况下,使用PriorityBinding会更容易。它将处理描述为null的情况,并为您使用类型:

<ComboBox>
  <ComboBox.ItemTemplate>
    <DataTemplate>
      <TextBlock>
         <TextBlock.Text>
           <PriorityBinding>
             <Binding Path="PhoneDescription" />
             <Binding Path="PhoneType" />
           </PriorityBinding>
         </TextBlock.Text>
      </TextBlock>
    </DataTemplate>
  </ComboBox.ItemTemplate>
</ComboBox>

答案 1 :(得分:0)

正如我所看到的,textblock绑定到PhoneTypesList返回的内容。然后就是使用转换器,它需要一个PhoneTypeRecord。 我想PhoneTypesList是PhoneTypeRecord的列表吗? 我注意到的是,在转换器中,我得到的完整列表并不是列表中的每个元素。所以你实际上得到了PhoneTypeRecord的list / collection / observableCollection。验证它。

您还可以在转换器中添加这样的条件:

if(value != typeof(what_you_are_expecting) throw new InvalidOperationException("something is wrong");