为什么在此 MultiBinding 上未调用 ConvertBack?
我的组合框列表“联系人”使用 MultiBinding 绑定到 FullName 和 PhoneExtension。 IMultiValueConverter 的 Convert 方法被调用,但 ConvertBack 未被调用。为什么? 组合框正确显示列表,但未保存选择。当我按 Tab 键离开时,它会消失。
背景:
1)联系人列表来自Web服务,并在后面的代码中放入可观察集合ContactListObservable中。我没有使用 ViewModel。
PhoneBookService phoneBookService = new PhoneBookService();
PhoneRecordArray pbs = GetCompletePhoneListing();
List<PhoneRecord> pbsList = pbs.PhoneArray.ToList();
ObservableCollection<Contact> observableContacts = new ObservableCollection<Contact>();
foreach(PhoneBookService.PhoneRecord rec in pbsList)
{
Contact c = new Contact();
c.FullName = rec.Person;
c.PhoneExtension = rec.Phone;
observableContacts.Add(c);
}
ContactListObservable = observableContacts;
2) 组合框位于用户控件上的数据网格中。这就是这种古怪绑定的原因: ItemsSource="{Binding ContactListObservable,relativeSource={RelativeSource FindAncestor, AncestorType=UserControl}}"
3) IMultiValueConverter 是 UserControl.Resources 中引用为 的类<本地:CombineNameAndPhoneExtensionMultiConverter x:Key="combinedNameAndPhoneExtensionConverter"/>
4) 在联系人列表中找不到的旧数据必须显示。这是通过结合显示值的 TextBlock 和用于编辑的 ComboBox 使用 DataGridTemplateColumn 来完成的。请参阅这篇 Julie Lerman MSDN 文章。
这是疯狂的 XAML:
<DataGridTemplateColumn x:Name="DataGridContactTemplateColumn" Header="Contact Using Template">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock>
<TextBlock.Text>
<MultiBinding StringFormat="{}{0} Ext. {1}">
<Binding Path="FullName"/>
<Binding Path="PhoneExtension"/>
</MultiBinding>
</TextBlock.Text>
</TextBlock>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
<DataGridTemplateColumn.CellEditingTemplate>
<DataTemplate x:Name="ContactsCellEditingTemplate">
<Grid FocusManager.FocusedElement="{Binding ElementName=ContactsTemplateComboBox}">
<ComboBox x:Name="ContactsTemplateComboBox" IsSynchronizedWithCurrentItem="False" IsEditable="False" IsDropDownOpen="True" ItemsSource="{Binding ContactListObservable, RelativeSource={RelativeSource FindAncestor, AncestorType=UserControl}}">
<ComboBox.ItemTemplate>
<DataTemplate>
<TextBlock DataContext="{Binding}">
<TextBlock.Text>
<MultiBinding Converter="{StaticResource combinedNameAndPhoneExtensionConverter}">
<Binding Path="FullName" UpdateSourceTrigger="PropertyChanged"/>
<Binding Path="PhoneExtension" UpdateSourceTrigger="PropertyChanged"/>
</MultiBinding>
</TextBlock.Text>
</TextBlock>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
</Grid>
</DataTemplate>
</DataGridTemplateColumn.CellEditingTemplate>
我为此投入了太多时间,因此我将非常感谢您提供的任何帮助。
更多背景:
包含我的组合框的数据网格每行包含一个实体框架联系人对象,并包含其他联系人字段。下面是一些有效的 XAML,它成功显示并保存 FullName,但不显示我想要与 FullName 结合保存的电话分机:
<DataGridTemplateColumn x:Name="DataGridContactTemplateColumn" Header="Contact Using Template">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding Path=FullName}"/>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
<DataGridTemplateColumn.CellEditingTemplate>
<DataTemplate x:Name="ContactsCellEditingTemplate">
<Grid FocusManager.FocusedElement="{Binding ElementName=ContactsTemplateComboBox}">
<ComboBox x:Name="ContactsTemplateComboBox" ItemsSource="{Binding ContactListObservable, RelativeSource={RelativeSource FindAncestor, AncestorType=UserControl}}" DisplayMemberPath="FullName" SelectedValuePath="FullName" Text="{Binding Path=FullName}" SelectedItem="{Binding Path=FullName}" IsSynchronizedWithCurrentItem="False" IsEditable="False" IsDropDownOpen="True"/>
</Grid>
</DataTemplate>
</DataGridTemplateColumn.CellEditingTemplate>
My combobox listing Contacts is bound to both FullName and PhoneExtension using MultiBinding. The Convert method of IMultiValueConverter is called but ConvertBack is not. Why? The combobox properly displays the list but the selection is not saved. It disappears when I tab away.
Background:
1) The Contact list comes from a web service and is put in an observable collection ContactListObservable in the code behind. I'm not using a ViewModel.
PhoneBookService phoneBookService = new PhoneBookService();
PhoneRecordArray pbs = GetCompletePhoneListing();
List<PhoneRecord> pbsList = pbs.PhoneArray.ToList();
ObservableCollection<Contact> observableContacts = new ObservableCollection<Contact>();
foreach(PhoneBookService.PhoneRecord rec in pbsList)
{
Contact c = new Contact();
c.FullName = rec.Person;
c.PhoneExtension = rec.Phone;
observableContacts.Add(c);
}
ContactListObservable = observableContacts;
2) The combobox is in a datagrid located on a UserControl. That's the reason for this wacky binding: ItemsSource="{Binding ContactListObservable, RelativeSource={RelativeSource FindAncestor, AncestorType=UserControl}}"
3) The IMultiValueConverter is a class referenced in UserControl.Resources as <local:CombineNameAndPhoneExtensionMultiConverter x:Key="combinedNameAndPhoneExtensionConverter"/>
4) Legacy data NOT found in the Contacts list must display. This is accomplished with a DataGridTemplateColumn by combining a TextBlock to display values and a ComboBox for editing. See this Julie Lerman MSDN article.
Here is the crazy XAML:
<DataGridTemplateColumn x:Name="DataGridContactTemplateColumn" Header="Contact Using Template">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock>
<TextBlock.Text>
<MultiBinding StringFormat="{}{0} Ext. {1}">
<Binding Path="FullName"/>
<Binding Path="PhoneExtension"/>
</MultiBinding>
</TextBlock.Text>
</TextBlock>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
<DataGridTemplateColumn.CellEditingTemplate>
<DataTemplate x:Name="ContactsCellEditingTemplate">
<Grid FocusManager.FocusedElement="{Binding ElementName=ContactsTemplateComboBox}">
<ComboBox x:Name="ContactsTemplateComboBox" IsSynchronizedWithCurrentItem="False" IsEditable="False" IsDropDownOpen="True" ItemsSource="{Binding ContactListObservable, RelativeSource={RelativeSource FindAncestor, AncestorType=UserControl}}">
<ComboBox.ItemTemplate>
<DataTemplate>
<TextBlock DataContext="{Binding}">
<TextBlock.Text>
<MultiBinding Converter="{StaticResource combinedNameAndPhoneExtensionConverter}">
<Binding Path="FullName" UpdateSourceTrigger="PropertyChanged"/>
<Binding Path="PhoneExtension" UpdateSourceTrigger="PropertyChanged"/>
</MultiBinding>
</TextBlock.Text>
</TextBlock>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
</Grid>
</DataTemplate>
</DataGridTemplateColumn.CellEditingTemplate>
I've devoted WAY too much time to this so I'll greatly appreciate any help you can offer.
More Background:
The datagrid containing my combobox contains one entity framework contact object per row and includes additional contact fields. Here is some working XAML that succesfully displays and saves FullName but not the phone extension which I want to save in combination with the FullName:
<DataGridTemplateColumn x:Name="DataGridContactTemplateColumn" Header="Contact Using Template">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding Path=FullName}"/>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
<DataGridTemplateColumn.CellEditingTemplate>
<DataTemplate x:Name="ContactsCellEditingTemplate">
<Grid FocusManager.FocusedElement="{Binding ElementName=ContactsTemplateComboBox}">
<ComboBox x:Name="ContactsTemplateComboBox" ItemsSource="{Binding ContactListObservable, RelativeSource={RelativeSource FindAncestor, AncestorType=UserControl}}" DisplayMemberPath="FullName" SelectedValuePath="FullName" Text="{Binding Path=FullName}" SelectedItem="{Binding Path=FullName}" IsSynchronizedWithCurrentItem="False" IsEditable="False" IsDropDownOpen="True"/>
</Grid>
</DataTemplate>
</DataGridTemplateColumn.CellEditingTemplate>
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
TextBlock 永远不会更改其 Text 属性,因此没有理由调用 ConvertBack 方法。您需要绑定到 ComboBox 的 SelectedItem 或 Text 属性才能获取更新。
The TextBlock will never change it's Text property, so there is no reason to call the ConvertBack method. You would need to be bind to either the ComboBox's SelectedItem or Text properties to get updates.
我正在回答我自己的问题,以详细说明 CodeNaked 的准确答案。 将其添加到问题 XAML 中,一切正常 - 调用 ConvertBack,并根据需要保存 FullName 和 PhoneExtension:
这是组合的NameAndPhoneExtensionConverter 代码:
感谢 CodeNaked 的快速回复!
I'm answering my own question to elaborate on CodeNaked's accurate answer. Add this to the problem XAML and everything works - ConvertBack is called and both FullName and PhoneExtension are saved as needed:
Here is the combinedNameAndPhoneExtensionConverter code:
Thanks CodeNaked for your fast reply!