c# - 转换器在绑定到 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>
解决方案
EF 使用该类型System.Data.Entity.DynamicProxies
作为代理来启用延迟加载。ObjectContext.ContextOptions.ProxyCreationEnabled
您可以通过设置为 false来禁用代理创建。关联
但是,建议使用 ViewModels 而不是 EF Models 作为绑定源。
您还可以将新属性添加到 EF 模型(或者最好添加到 VM)作为每个项目的绑定源:
[NotMapped]
public string FirstLastName { get { return FirstName + ", " + LastName; } }
您应该记住DataContext
ofItemTemplate
指的是集合的每个元素。所以类型对象的路径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]);
}
推荐阅读
- azure - 是否有可能仅为 Sharepoint online 创建条件访问策略,不包括其依赖项,如 ms 团队?
- ansible - Ansible 失败的未定义变量
- python - 芹菜作业中的 Threadpool Python 未来似乎正在阻塞
- java - 尽管有 Retrolambda,但与缺乏支持 java 8 相关的错误
- equality - 如何在 Agda 中定义观察相等
- kubernetes - FluentBit 不从共享 PVC 读取日志
- javascript - Javascript,如何将父函数参数传递给带有回调参数的子函数?
- java - 如何注入 Set
在 Setter 注入中使用基于注释的配置? - python - 遍历数据框中的所有行并根据比较其他列生成新列
- postgresql - Postgres sink 连接器在 DLQ 中放置消息