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

。_饼干妹妹 提交于 2020-01-30 08:17:06

问题


I am writing a WPF MVVM Application. I am trying to use a converter to display a contact name in the combobox. I do not think I can use the DisplayMemberPath since a "fullname" column does not exist.

The ComboBox is being bound to a class within a class using Entity Framework. Given the following:

.cs Files

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 file

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

The issue is that the end result that is displayed in the ComboBox is:

System.Data.Entity.DynamicProxies.Contact_.......

It is not showing the Owner name in the correct format. How can I do a binding to the ComboBox in this manner to get the output I desire (ie. Doe Sr., John Michael, Mr.)

EDIT I have also tried it this way

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


The type System.Data.Entity.DynamicProxies is used by EF as a proxy to enable lazy loading. You can disable proxy creation by setting ObjectContext.ContextOptions.ProxyCreationEnabled to false. link

However, it is recommended to use ViewModels as the source of the binding instead of EF Models.

You can also add a new property to an EF Model (or preferably to a VM) as the source of the bindings of each item:

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

link


You should keep in mind that DataContext of ItemTemplate refers to each element of a collection. So the path of an object of type Contact is . not Contacts.

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

I also noticed that you used a multi value converter with one value. You could do it like the following:

<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]);
}


来源:https://stackoverflow.com/questions/51331849/converter-shows-system-data-entity-dynamicproxies-when-bind-to-ef-model

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!