2

私のコンボボックス リストの Contacts は、MultiBinding を使用して FullName と PhoneExtension の両方にバインドされています。IMul​​tiValueConverter の Convert メソッドが呼び出されますが、ConvertBack は呼び出されません。なんで?コンボボックスはリストを正しく表示しますが、選択は保存されません。タブを離すと消えます。

バックグラウンド:

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) コンボボックスは、UserControl にあるデータグリッドにあります。それが、この奇抜なバインディングの理由です。ItemsSource="{Binding ContactListObservable, RelativeSource={RelativeSource FindAncestor, AncestorType=UserControl}}"

3) IMultiValueConverter は、UserControl.Resources で参照されるクラスです。<local: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>

私はこれにあまりにも多くの時間を費やしてきたので、あなたが提供できる助けに大いに感謝します.

その他の背景:

私のコンボボックスを含むデータグリッドには、行ごとに 1 つのエンティティ フレームワークの連絡先オブジェクトが含まれ、追加の連絡先フィールドが含まれています。FullName を正常に表示して保存するが、FullName と組み合わせて保存したい電話の内線番号は表示しない、いくつかの動作中の XAML を次に示します。

<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>

4

2 に答える 2

2

TextBlock はその Text プロパティを決して変更しないため、ConvertBack メソッドを呼び出す理由はありません。更新を取得するには、ComboBox の SelectedItem プロパティまたは Text プロパティのいずれかにバインドする必要があります。

于 2011-06-28T17:13:23.990 に答える
0

私はCodeNakedの正確な答えを詳しく説明するために、私自身の質問に答えています。これを問題のXAMLに追加すると、すべてが機能します-ConvertBackが呼び出され、必要に応じてFullNameとPhoneExtensionの両方が保存されます。

<ComboBox.SelectedItem>
    <MultiBinding Converter="{StaticResource combinedNameAndPhoneExtensionConverter}">
        <Binding Path="FullName" UpdateSourceTrigger="PropertyChanged"/>
        <Binding Path="PhoneExtension" UpdateSourceTrigger="PropertyChanged"/>
    </MultiBinding>
</ComboBox.SelectedItem>

これがcombinedNameAndPhoneExtensionConverterコードです:

public class CombineNameAndPhoneExtensionMultiConverter : IMultiValueConverter
{
    public object Convert(object[] values,
                          Type targetType,
                          object parameter,
                          System.Globalization.CultureInfo culture)
    {
        if (values[0] as string != null)
        {
            string fullName = (string)values[0];
            string phoneExtension = (string)values[1];
            string namePlusExtension = fullName + ", " + phoneExtension;
            return namePlusExtension;
        }
        return null;
    }

    public object[] ConvertBack(object value,
                                Type[] targetTypes,
                                object parameter,
                                System.Globalization.CultureInfo culture)
    {
        Contact c = (Contact)value;

        string[] returnValues = { c.FullName, c.PhoneExtension };
        return returnValues;
    }

}

迅速な返信をありがとうCodeNaked!

于 2011-06-28T19:43:37.590 に答える