绑定到EF模型时,转换器显示System.Data.Entity.DynamicProxies

时间:2018-07-13 19:40:24

标签: c# wpf combobox binding imultivalueconverter

我正在编写WPF MVVM应用程序。我正在尝试使用转换器在组合框中显示联系人姓名。我不认为我可以使用DisplayMemberPath,因为“全名”列不存在。

使用Entity Framework将ComboBox绑定到类中的一个类。给出以下内容:

.cs文件

public class Car
{
    public int CarId { get; set; }
    public string Make { get; set; }
    public string Model { get; set; }
    public string Year { get; set; }
    public Contact Owner { get; set; }
}

public class Contact 
{
    public int ContactID { get; set; }
    public string Salutation { get; set; }
    public string FirstName { get; set; }
    public string MiddleName { get; set; }
    public string LastName { get; set; }
    public string Suffix { get; set; }
}

public class MultiBindingConverter : IMultiValueConverter
{
    public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
    {
        string name = "";
        if (!(values[0] is Contact Contact))
            return name;

        switch ((string)parameter)
        {
            case "LastNameFirst":
            name += (!string.IsNullOrEmpty(Contact.LastName)) ? Contact.LastName : "";
            name += (!string.IsNullOrEmpty(Contact.Suffix)) ? " " + Contact.Suffix : "";
            name += (!string.IsNullOrEmpty(Contact.FirstName)) ? ", " + Contact.FirstName : "";
            name += (!string.IsNullOrEmpty(Contact.MiddleName)) ? " " + Contact.MiddleName : "";
            name += (!string.IsNullOrEmpty(Contact.Salutation)) ? ", " + Contact.Salutation : "";

            break;
        case "FormatNormal":
        default:
            name += (!string.IsNullOrEmpty(Contact.Salutation)) ? Contact.Salutation : "";
            name += (!string.IsNullOrEmpty(Contact.FirstName)) ? " " + Contact.FirstName : "";
            name += (!string.IsNullOrEmpty(Contact.MiddleName)) ? " " + Contact.MiddleName : "";
            name += (!string.IsNullOrEmpty(Contact.LastName)) ? " " + Contact.LastName : "";
            name += (!string.IsNullOrEmpty(Contact.Suffix)) ? " " + Contact.Suffix : "";
            break;
    }

    return name;
}

public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
{
    throw new NotImplementedException();
}
}

.XAML文件

<UserControl.Resources>
    <local:MultiBindingConverter x:Key="MBC" />
</UserControl.Resources>

<ComboBox ItemsSource="{Binding Contacts, Mode=OneTime}" // Contacts is a full list of the Contact Class (so its every Owner)
          SelectedValuePath="ContactId"
          SelectedValue="{Binding Car.Owner.ContactId, Mode=TwoWay}"
          >
<ComboBox.ItemTemplate>
    <DataTemplate>
         <TextBlock>
             <TextBlock.Text>
                  <MultiBinding Converter="{StaticResource MBC}" ConverterParameter="LastNameFirst" >
                      <Binding Path="Contacts"/>
                  </MultiBinding>
             </TextBlock.Text>
         </TextBlock>
    </DataTemplate>
 </ComboBox.ItemTemplate>
 </ComboBox>

问题在于ComboBox中显示的最终结果是:

  

System.Data.Entity.DynamicProxies.Contact _.......

它没有以正确的格式显示所有者名称。我如何以这种方式绑定到ComboBox以获得我想要的输出(即,Doe Sr.,John Michael,先生)

EDIT 我也尝试过这种方式

.cs IValueConverter

public class ContactNameConverter : BaseValueConverter<ContactNameConverter>
{
    public override object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {

        string name = "";
        if (!(value is Contact Contact))
            return name;

        switch ((string)parameter)
        {
            case "LastNameFirst":
                name += (!string.IsNullOrEmpty(Contact.LastName)) ? Contact.LastName : "";
                name += (!string.IsNullOrEmpty(Contact.Suffix)) ? " " + Contact.Suffix : "";
                name += (!string.IsNullOrEmpty(Contact.FirstName)) ? ", " + Contact.FirstName : "";
                name += (!string.IsNullOrEmpty(Contact.MiddleName)) ? " " + Contact.MiddleName : "";
                name += (!string.IsNullOrEmpty(Contact.Salutation)) ? ", " + Contact.Salutation : "";

                break;
            case "FormatNormal":
            default:
                name += (!string.IsNullOrEmpty(Contact.Salutation)) ? Contact.Salutation : "";
                name += (!string.IsNullOrEmpty(Contact.FirstName)) ? " " + Contact.FirstName : "";
                name += (!string.IsNullOrEmpty(Contact.MiddleName)) ? " " + Contact.MiddleName : "";
                name += (!string.IsNullOrEmpty(Contact.LastName)) ? " " + Contact.LastName : "";
                name += (!string.IsNullOrEmpty(Contact.Suffix)) ? " " + Contact.Suffix : "";
                break;
        }

        return name;

    }

    public override object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        throw new NotImplementedException();
    }

}

.XAML

<ComboBox ItemsSource="{Binding Contacts, Mode=OneTime}"
      SelectedValuePath="ContactId"
      SelectedValue="{Binding Car.Owner.ContactId, Mode=TwoWay}"
      >
      <ComboBox.ItemTemplate>
          <DataTemplate>
               <TextBlock Text="{Binding Path=., Converter={local:ContactNameConverter}}"/>
          </DataTemplate>
      </ComboBox.ItemTemplate>
 </ComboBox>

1 个答案:

答案 0 :(得分:0)

EF使用System.Data.Entity.DynamicProxies类型作为代理来启用延迟加载。您可以通过将ObjectContext.ContextOptions.ProxyCreationEnabled设置为false来禁用代理创建。 link

但是,建议使用ViewModels作为绑定源而不是EF模型。

您还可以将新属性添加到EF模型(最好是添加到VM)作为每个项目的绑定源:

 [NotMapped]
 public string FirstLastName { get { return FirstName + ", " + LastName; } } 

link


请记住,DataContext中的ItemTemplate引用了集合中的每个元素。因此,类型Contact的对象的路径是.而不是Contacts

<ComboBox.ItemTemplate>
    <DataTemplate>
         <TextBlock>
             <TextBlock.Text>
                  <MultiBinding Converter="{StaticResource MBC}" ConverterParameter="LastNameFirst" >
                      <Binding Path="."/>
                  </MultiBinding>
             </TextBlock.Text>
         </TextBlock>
    </DataTemplate>
 </ComboBox.ItemTemplate>

我还注意到您使用了一个带有一个值的多值转换器。您可以按照以下方式进行操作:

<ComboBox.ItemTemplate>
    <DataTemplate>
         <TextBlock>
             <TextBlock.Text>
                  <MultiBinding Converter="{StaticResource MBC}" ConverterParameter="LastNameFirst" >
                      <Binding Path="FirstName"/>
                      <Binding Path="LastName"/>
                  </MultiBinding>
             </TextBlock.Text>
         </TextBlock>
    </DataTemplate>
 </ComboBox.ItemTemplate>

public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
{
     if(parameter == "LastNameFirst")
        return string.Format("{0}, {1}", values[0], values[1]);
     else
        return string.Format("{0}, {1}", values[1], values[0]);
}