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

Converter shows System.Data.Entity.DynamicProxies when bind to EF Model

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

ComboBox 正在使用 Entity Framework 绑定到 class 中的 class。鉴于以下内容:

.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,Mr.)

编辑 我也试过这种方法

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

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

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

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

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

link


您应该记住 DataContext of 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]);
}