【问题标题】:How do I bind a GridViewComboBoxColumn to multiple fields?如何将 GridViewComboBoxColumn 绑定到多个字段?
【发布时间】:2013-02-21 14:03:30
【问题描述】:

我的 GridViewComboBox ItemsSource 是一个可观察的联系人集合。它在两列中同时显示 FullName 和 PhoneExtension。组合框是我的 Telerik WPF RadGridView 中的一列。 GridViewComboBoxColumn(不工作)xaml 如下所示:

<telerik:GridViewComboBoxColumn Name="contactsComboBox"  Header="Contact"
   DisplayMemberPath="FullName"
   SelectedValueMemberPath="FullName"
   ItemsSource="{Binding ContactListObservable}"
   DataMemberBinding="{Binding PhoneExtension}" >

    <telerik:GridViewComboBoxColumn.ItemTemplate>
        <DataTemplate>
            <Grid>
                <Grid.ColumnDefinitions>
                    <ColumnDefinition  Width="Auto" />
                    <ColumnDefinition Width="Auto" />
                    <ColumnDefinition Width="Auto" />
                </Grid.ColumnDefinitions>

                <TextBlock Text="{Binding FullName}" />
                <TextBlock Text="    Phone: "  Grid.Column="1" />
                <TextBlock Text="{Binding PhoneExtension}"  Grid.Column="2" />
            </Grid>
        </DataTemplate>
    </telerik:GridViewComboBoxColumn.ItemTemplate>
</telerik:GridViewComboBoxColumn>

我想同时绑定 FullName 和 PhoneExtension,但似乎 DataMemberBinding 中只能有一个字段。我不确定 DisplayMemberPath 或 SelectedValueMemberPath 中的内容。

我也愿意使用事件而不是绑定。如果您可以同时显示 AddHandler 和组合框的 SelectionChangedEvent 的代码,将不胜感激。

如何将我的多列 GridViewComboBox 绑定到多个字段?

【问题讨论】:

    标签: c# wpf xaml data-binding telerik


    【解决方案1】:

    您好,一种方法是覆盖 ToString() 方法,另一种方法是使用 Converter。

        public partial class MainWindow
    {
        public MainWindow()
        {
            InitializeComponent();
            DataContext = this;
            Students = new ObservableCollection<Student>();
            Students.Add(new Student() { Name = "abc", RollNo = 1, Course = "MCA" });
            Students.Add(new Student() { Name = "xyz", RollNo = 1, Course = "MCA" });
            Students.Add(new Student() { Name = "pqr", RollNo = 1, Course = "MCA" });
            Students.Add(new Student() { Name = "stu", RollNo = 1, Course = "MCA" });
        }
        public ObservableCollection<Student> Students { get; set; }
    }
    
    public  class Student
    {
        public string Name { get; set; }
        public string Course  { get; set; }
        public int RollNo { get; set; }
    
        public override string ToString()
        {
            return this.Name + "  " + this.Course;
        }
    }
    
    <ComboBox ItemsSource="{Binding Students}"/>
    

    另一种方法是使用 Converter 之类的

        public class MyConverter : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
    
            if (value is Student)
                return ((Student)value).Name + "  " + ((Student)value).Course;
            else
                return null;
    
        }
    
        public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            throw new NotImplementedException();
        }
    }
    

    我希望这会给你一个想法。

    【讨论】:

    • 我希望绑定是双向的。姓名和电话保存在单独的数据库字段中。那么在转换器中我需要 ConvertBack 代码吗?
    • 您可以轻松地将它们从您的 Selected Item 中提取出来,我认为不需要转换回来。
    • 如何编写 GridViewComboBox 绑定语句,以便当用户选择联系人时,它会同时绑定到 FullName 和 PhoneExtension 字段?
    • 我认为 FullName 和 PhoneExtension 字段属于同一个类,它是这个类的集合绑定到 ComboBox。
    【解决方案2】:

    我认为将 MultiBinding 与 MultiValueConverter 一起使用应该可以解决问题。参考this MSDN page上的例子

    该示例显示了如何将文本属性绑定到从 2 个绑定属性 FirstName 和 LastName 计算的值

    <telerik:GridViewComboBoxColumn  
                        ItemsSource="{Binding}">
       <telerik:GridViewComboBoxColumn.DisplayMemberBinding>
          <MultiBinding Converter="{StaticResource myNameConverter}"
                      ConverterParameter="FormatLastFirst">
             <Binding Path="FullName"/>
             <Binding Path="PhoneExt"/>
          </MultiBinding>  
       </telerik:GridViewComboBoxColumn.DisplayMemberBinding>
    

    DisplayMemberBinding 看起来就像您希望组合框下拉显示的内容。 DataMemberBinding 是您想要获取/设置回商店的内容。例如您可以向用户显示“电话号码,分机”,但在选择更改时,只会修改电话分机值。

    【讨论】:

    • 谢谢。我认为你有一个错字......没有 DisplayMemberBinding 属性。当我将它更改为 DataMemberBinding 时,我得到了这个异常: DataMemberBinding 不允许使用 MultiBinding,因为它不是依赖属性。我将尝试在属性 DisplayMemberPath 上使用 MultiBinding。我也会研究你的链接。
    • @DeveloperDan - 是的,我在猜那里 - 不要使用 Telerik 控制。我只是希望对称。
    【解决方案3】:

    这是我解决这个问题的方法(我正在回答我自己的问题)。

    首先是我使用的 Multibinding TypeConverters:

    public class CombineFullNameAndPhoneExtensionMultiConverter : 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] ?? "Unknown";
                string phoneExtension = (string)values[1] ?? "Unknown";
                string namePlusExtension = fullName.Trim() + "    Phone: " + phoneExtension.Trim();
                return namePlusExtension;
            }
            return null;
        }
    
        public object[] ConvertBack(object value,
                                    Type[] targetTypes,
                                    object parameter,
                                    System.Globalization.CultureInfo culture)
        {
            NotesContact c = (NotesContact)value;
    
            string[] returnValues = { c.FullName.Trim(), c.PhoneExtension.Trim() };
            return returnValues;
        }
    }
    
    public class CombineLastNameFirstNameAndPhoneExtensionMultiConverter : IMultiValueConverter
    {
        public object Convert(object[] values,
                             Type targetType,
                             object parameter,
                             System.Globalization.CultureInfo culture)
       {
           if (values[0] as string != null)
           {
               string lastName = (string)values[0] ?? "Unknown";
               string firstName = (string)values[1] ?? "Unknown";
               string phoneExtension = (string)values[2] ?? "Unknown";
    
               string lastCommaFirstPlusExtension = lastName.Trim() + ", " + firstName.Trim() + "    Phone: " + phoneExtension.Trim();
               return lastCommaFirstPlusExtension;
           }
           return null;
       }
    
       public object[] ConvertBack(object value,
                                   Type[] targetTypes,
                                   object parameter,
                                   System.Globalization.CultureInfo culture)
       {
           throw new NotImplementedException();
       }
    }
    

    以下是 xaml 中的 Converter 声明:

    <local:CombineFullNameAndPhoneExtensionMultiConverter x:Key="combinedFullNameAndPhoneExtensionConverter"/>
    <local:CombineLastNameFirstNameAndPhoneExtensionMultiConverter x:Key="combinedLastNameFirstNameAndPhoneExtensionConverter"/>
    

    现在这里是 ComboBox xaml:

    <telerik:GridViewComboBoxColumn Name="contactsGridViewComboBox"  Header="Contact"
            ItemsSource="{Binding ContactListObservable, RelativeSource={RelativeSource FindAncestor, AncestorType=UserControl}}">
    <telerik:GridViewComboBoxColumn.CellTemplate>
        <DataTemplate>
            <TextBlock>
                <TextBlock.Text>
                    <MultiBinding  Converter="{StaticResource combinedFullNameAndPhoneExtensionConverter}">
                            <Binding Path="FullName"/>
                            <Binding Path="PhoneExtension"/>
                    </MultiBinding>
                </TextBlock.Text>
            </TextBlock>
        </DataTemplate>
    </telerik:GridViewComboBoxColumn.CellTemplate>
    <telerik:GridViewComboBoxColumn.CellEditTemplate>
        <DataTemplate x:Name="ContactsCellEditTemplate">
            <Grid FocusManager.FocusedElement="{Binding ElementName=ContactsTemplateComboBox}">
                <telerik:RadComboBox x:Name="ContactsTemplateComboBox" IsSynchronizedWithCurrentItem="False" IsEditable="False" ItemsSource="{Binding ContactListObservable, RelativeSource={RelativeSource FindAncestor, AncestorType=UserControl}}"  IsDropDownOpen="True" TextSearchMode="Contains" IsFilteringEnabled="True" OpenDropDownOnFocus="True">
                    <telerik:RadComboBox.SelectedItem>
                        <MultiBinding Converter="{StaticResource combinedFullNameAndPhoneExtensionConverter}">
                            <Binding Path="FullName" UpdateSourceTrigger="PropertyChanged"/>
                            <Binding Path="PhoneExtension" UpdateSourceTrigger="PropertyChanged"/>
                        </MultiBinding>
                    </telerik:RadComboBox.SelectedItem>
                    <telerik:RadComboBox.ItemTemplate>
                        <DataTemplate>
                            <TextBlock DataContext="{Binding}">
                                <TextBlock.Text>                                                        
                                    <MultiBinding  Converter="{StaticResource combinedLastNameFirstNameAndPhoneExtensionConverter}">                             
                                        <Binding Path="LastName"/>                                                                                                                                                             <Binding Path="FirstName" />
                                        <Binding Path="PhoneExtension"/>
                                    </MultiBinding>
                                </TextBlock.Text>
                            </TextBlock>
                        </DataTemplate>
                    </telerik:RadComboBox.ItemTemplate>
                </telerik:RadComboBox>
            </Grid>
        </DataTemplate>
    </telerik:GridViewComboBoxColumn.CellEditTemplate>
    

    注意我已经使用了 MultibindingCellTemplate(在查看模式下获取或设置单元格的数据模板)和 CellEditTemplate (获取或设置处于编辑模式的单元格的数据模板)。由于我的时间不多了,我让代码自己说话。如果您需要澄清,请发表评论,如果这太令人困惑,请发布新的 Stack Overflow 问题。我非常感谢 SO 社区。你摇滚!

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-03-07
      • 2011-04-23
      • 2012-10-30
      • 2015-06-18
      • 2010-11-11
      相关资源
      最近更新 更多