WPF DataGrid绑定到导航属性

时间:2016-03-28 12:42:16

标签: c# wpf entity-framework data-binding datagrid

我在Visual Studio 2015中使用Entity Framework 6来创建一个带有DataGrid的WPF应用程序。它需要绑定到包含3层深度的实体框架导航属性的搜索结果:员工可以有任意数量的EmployeeStatus,而EmployeeStatus可以拥有EmployeeStatusDescription实体。所以它看起来像这样:

  

员工> EmployeeStatus> EmployeeStatusDescription

我有以下Include()

var comparison = Expression.Lambda<Func<Employee, bool>>(
    Expression.Equal(
        Expression.Property(paramEmployee, selectedColumnValue),
        Expression.Constant(SearchValue)), 
        paramEmployee).Compile();

var query = (from e in Context.Employees
             .Include("EmployeeStatus.EmployeeStatusDescription")
             .Where(comparison)
             select e); 

我尝试像这样绑定EmployeeStatusDescription:

<DataGrid ItemsSource="{Binding SearchResults}">
    <!-- other columns here... -->
    <DataGridTextColumn Binding="{Binding 
      EmployeeStatus.EmployeeStatusDescription.description}" Header="Status" />
</DataGrid>

但对于Status Employee以及相关的导航属性EmployeeStatusEmployeeStatusDescription列显示为空白。

但是,在数据库上,以下SQL将EmployeeStatusDescription带回来就好了:

select esd.* from employee e
    left join EmployeeStatus es on e.employeeID = es.employeeID
    left join EmployeeStatusDescription esd on 
       es.employeeStatusDescriptionID = esd.employeeStatusDescriptionID
where e.employeeID = '30299'

我做错了什么?谢谢你的帮助。

更新1 :EmployeeStatus在我的员工模型中定义,因此它是一个集合,而不仅仅是一个值:

public virtual ICollection<EmployeeStatu> EmployeeStatus { get; set; }

更新2 :这是EmployeeStatusDescription类:

public partial class EmployeeStatusDescription
{
    [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors")]
    public EmployeeStatusDescription()
    {
        this.EmployeeStatus = new HashSet<EmployeeStatu>();
    }

    public int employeeStatusDescriptionID { get; set; }
    public string employeeStatusAbbreviation { get; set; }
    public string description { get; set; }
    public bool isActive { get; set; }
    public System.DateTime createdDate { get; set; }

    [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
    public virtual ICollection<EmployeeStatu> EmployeeStatus { get; set; }
}

1 个答案:

答案 0 :(得分:1)

如果EmployeeStatus是一个集合,您将无法只说EmployeeStatus.EmployeeStatusDescription.description。 .NET不知道要吐回哪一个。您可以创建一个IValueConverter,它接收一个集合并返回第一个集合。

或者,您可以在viewmodel上创建一个属性,该属性返回EmployeeStatus集合中的第一个项目

    public EmployeeStatus FirstStatus{
       get { if (EmployeeStatus != null) { return EmployeeStatus.First(); } return null; }
    }

或者您可以添加一个内容控件,该控件将绑定到EmployeeStatus集合中的所有项目并列出所有项目。

修改 要显示员工的数据网格内的所有值,您需要另一个控件来迭代集合。在显示EmployeeStatus的列中,您需要将其设置为模板列并添加可以执行迭代的控件:

<DataGridTemplateColumn Header="Employee Status">
     <DataGridTemplateColumn.CellTemplate>
           <DataTemplate>
               <ListBox ItemsSource="{Binding Source=EmployeeStatus}">
                   <ListBox.ItemTemplate>
                       <DataTemplate>
                           <TextBlock Text="{Binding EmployeeStatusDescription.description}" />
                      </DataTemplate>
                   </ListBox.ItemTemplate>
                </ListBox>
          </DataTemplate>
      </DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>

项目控制绑定

<DataGridTemplateColumn Header="Employee Status">
         <DataGridTemplateColumn.CellTemplate>
               <DataTemplate>
                    <ItemsControl ItemsSource="{Binding EmployeeStatus}">
                         <ItemsControl.ItemTemplate>
                             <DataTemplate>
                                  <TextBlock Text="{Binding EmployeeStatusDescription.description}" />
                             </DataTemplate>
                         </ItemsControl.ItemTemplate>
                     </ItemsControl>
                <DataTemplate>
           <DataGridTemplateColumn.CellTemplate>
  </DataGridTemplateColumn>