首页 > 解决方案 > 转换器在绑定到 EF 模型时显示 System.Data.Entity.DynamicProxies

问题描述

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

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

标签: c#wpfcomboboxbindingimultivalueconverter

解决方案


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

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

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

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

关联


您应该记住DataContextofItemTemplate指的是集合的每个元素。所以类型对象的路径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]);
}

推荐阅读