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