如何使用 MVVM light 加载带有两个相关表的 DataGrid,我使用的是 .NET RIA 和 silverlight 4。
例如,如果我的数据表是:
userInfo- userID、Name、AddressID
地址 - AddressID、StreetName、Zip
如何创建显示 [Name, StreetName, ZIp] 的数据网格
如何使用 MVVM light 加载带有两个相关表的 DataGrid,我使用的是 .NET RIA 和 silverlight 4。
例如,如果我的数据表是:
userInfo- userID、Name、AddressID
地址 - AddressID、StreetName、Zip
如何创建显示 [Name, StreetName, ZIp] 的数据网格
首先,您必须在您的 DomainService 类中的 UserInfo 的 GetQuery 中包含地址表,如下所示...
[Query]
public IQueryable<UserInfo> GetUserInfos()
{
return this.ObjectContext.UserInfos.Include("Address");
}
然后在元数据文件中,你必须在上面添加 [Include]
[Include]
public Addresses Address{ get; set; }
public int AddressID { get; set; }
现在构建解决方案。现在在 Xaml 中你可以像这样使用
<sdk:DataGrid ItemsSource="{Binding UserList, Mode=TwoWay}" SelectedItem="{Binding CurrentUser, Mode=TwoWay}" Margin="0,0,0,2" AutoGenerateColumns="False">
<sdk:DataGrid.Columns>
<sdk:DataGridTextColumn Header="Name" Binding="{Binding Path=Name}"/>
<sdk:DataGridTextColumn Header="Street Name" Binding="{Binding Path=Address.StreetName}"/>
<sdk:DataGridTextColumn Header="Zip" Binding="{Binding Path=Address.Zip}"/>
</sdk:DataGrid.Columns>
</sdk:DataGrid>
这里有几种可能的方法。我会解释这两个想到的。首先,使用数据库中已经定义的关系。其次是通过自定义模型类返回。
选项 1:我假设您已经从 Web 项目的数据库中创建了一个实体框架模型(具有关系),并创建了 DomainService 来托管该模型。!!!创建模型时要做的一个关键是为模型创建元数据类!!!(我在前几次错过了这一点,修改模型的行为至关重要,例如您需要的)
在元数据模型中,您将找到关联属性,并使用 [Include] 属性对其进行装饰。这是我从另一个带有 WorklanDetail 的项目中获得的示例,我想在其中返回关联的分配:
[MetadataTypeAttribute(typeof(WorkplanDetailMetadata))]
public partial class WorkplanDetail
{
internal sealed class WorkplanDetailMetadata
{
[Include]
public EntityCollection<Assignment> Assignments { get; set; }
}
}
然后,您只需在 Silverlight 应用程序中引用该属性,就可以使用您的地址数据。
要绑定单个实体(实体引用,而不是集合),那么您只需使用您的属性来访问数据网格绑定上的子实体......例如:
Text="{Binding Path=Address.StreetName}"
这是我所知道的最简单的方法。
选项 2 需要创建您自己的自定义类(您必须至少有一个用 [Key] 属性装饰的属性,以方便与客户端之间的传输)。下面是一个例子,我曾经用来获取文件夹搜索结果信息:
public class FolderSearchResult
{
[Key]
public string EFOLDERID { get; set; }
public string Subject { get; set; }
public string FolderName { get; set; }
}
关键是 EFOLDERID 属性具有 [Key] 属性,该属性唯一标识每个项目,就像数据库中的 PK 一样。
然后在您的服务类中,您可以像这样返回:
public IEnumerable<FolderSearchResult> GetFolderResults(string search)
{
var query = from ge in this.ObjectContext.Generic_Engagement
from f in this.ObjectContext.eFolders
where ge.EFOLDERID == f.eFolderID &
f.eArchived == 0 &
f.eSubject.Contains(search) &
(from wp in this.ObjectContext.Workplans
where wp.EFOLDERID == f.eFolderID
select wp).Count() == 0 &
(from r in this.ObjectContext.Resources
where r.EFOLDERID == f.eFolderID
select r).Count() == 0
select new FolderSearchResult()
{
EFOLDERID = f.eFolderID,
FolderName = f.eFolderName,
Subject = f.eSubject
};
return query.AsEnumerable<FolderSearchResult>();
}
关于这种方法的几点说明:
总之,我建议使用第一种方法,除非发生以下情况:您需要一个跨越数据存储(单独的数据库源)的逻辑对象,或者您需要快速只读访问(例如下拉列表的 ItemSource 绑定)。
将排序和过滤逻辑卸载到服务器,即使以在内存中加载额外实体为代价,以便您的客户端可以保持快速,根据我的经验,这是有好处的。在 CollectionViewSource 中使用本地排序或其他东西可以做同样的事情,但其中的一些可能会真正开始减慢您的应用程序速度。