使用LINQ的数据绑定gridview

时间:2010-05-27 19:46:43

标签: linq data-binding datagrid drop-down-menu

我有两个数据库表,一个用于网站用户,包含字段“UserID”,“Name”和外键“PageID”。另一个是“PageID”字段(这里是主键)和“Url”。

我希望能够使用来自两个表的数据在gridview中显示数据,并且我想在aspx页面中使用数据绑定来完成。

我不知道该怎么做,但我找不到这种特殊情况的好例子。这是我到目前为止所做的:

  <%@ Page Title="Home Page" Language="C#" MasterPageFile="~/Site.master" AutoEventWireup="true"
    CodeBehind="Default.aspx.cs" Inherits="LinqBinding._Default" %>

<asp:Content ID="HeaderContent" runat="server" ContentPlaceHolderID="HeadContent">
</asp:Content>
<asp:Content ID="BodyContent" runat="server" ContentPlaceHolderID="MainContent">
    <h2>
        Testing LINQ
    </h2>
    <asp:GridView ID="GridView1" runat="server" DataSourceID="LinqDataSourceUsers" AutoGenerateColumns="false">
        <Columns>
            <asp:CommandField ShowSelectButton="True" />
            <asp:BoundField DataField="UserID" HeaderText="UserID" />
            <asp:BoundField DataField="Name" HeaderText="Name" />
            <asp:BoundField DataField="PageID" HeaderText="PageID" />
            <asp:TemplateField HeaderText="Pages">
            <ItemTemplate
                <asp:DropDownList ID="DropDownList1"
                 DataSourceID="LinqDataSourcePages"
                 SelectedValue='<%#Bind("PageID") %>'
                 DataTextField="Url"
                 DataValueField="PageID"
                 runat="server">
                </asp:DropDownList>
            </ItemTemplate>
            </asp:TemplateField>           
        </Columns>
    </asp:GridView>
    <asp:LinqDataSource ID="LinqDataSourcePages" runat="server" 
    ContextTypeName="LinqBinding.UserDataContext" EntityTypeName="" 
        TableName="Pages">
    </asp:LinqDataSource>
    <asp:LinqDataSource ID="LinqDataSourceUsers" runat="server" 
        ContextTypeName="LinqBinding.UserDataContext" EntityTypeName="" 
        TableName="Users">
    </asp:LinqDataSource>
</asp:Content>

但是这只能在用户表进入gridview时才会起作用(这不是问题),我将页面数据放入下拉列表中,但问题是:我当然得到了所有的页面数据在那里,不仅仅是每行上每个用户的页面。那么如何在每行的下拉列表中设置某种“where”约束来仅显示该行中用户的页面? (另外,说实话,我不确定我是否正确得到外键关系,因为我不太习惯于处理关系)。

编辑:

我认为我已经错误地建立了这种关系。我不断收到“Pages”作为User对象上的属性不存在的消息。我想这不可能,因为现在的关系是单向的。所以我试图建立一个多对多的关系。同样,我的数据库知识有点受限,但我添加了一个所谓的“联结表”,其中包含UserID和PageID字段,与其他表的主键相同。虽然我无法在联结表中制作这两个主键(看起来有些人在我见过的例子中看到了......但是因为我不可能猜到它们不应该这样)。无论如何,我从每个表创建了一个关系,并从中创建了新的LINQ类。

但那我该怎么办?我将联结表设置为Linq数据源,因为我猜我必须这样做才能访问这两个表,但这不起作用。然后它抱怨该对象上没有Name属性。那么如何访问相关表格呢?

(顺便说一句:这是我查找解决方案的一个页面:http://www.iaingalloway.com/2015/06/many-to-many-relationships-in-linq-to-sql.html,但首先我不明白他如何修改“Order”类代码隐藏。我只能进入上下文类(我无法在设计视图中右键单击该类,因为他建议并查看代码...),并且在那里似乎没有任何方式可以引用连接类 - 在他的情况下为Order_Details)..我错过了什么吗?)

以下是我现在与多对多关系的内容:

 <%@ Page Title="Home Page" Language="C#" MasterPageFile="~/Site.master" AutoEventWireup="true"
    CodeBehind="Default.aspx.cs" Inherits="ManyToMany._Default" %>

<asp:Content ID="HeaderContent" runat="server" ContentPlaceHolderID="HeadContent">
</asp:Content>
<asp:Content ID="BodyContent" runat="server" ContentPlaceHolderID="MainContent">
    <h2>
        Many to many LINQ
    </h2>
    <asp:GridView ID="GridView1" runat="server" DataSourceID="LinqDataSource1" AutoGenerateColumns="false">
    <Columns>
        <asp:CommandField ShowSelectButton="True" />
        <asp:BoundField DataField="UserID" HeaderText="UserID" />
        <asp:BoundField DataField="Name" HeaderText="Name" />
        <asp:BoundField DataField="PageID" HeaderText="PageID" />
        <asp:TemplateField HeaderText="Pages">
        <ItemTemplate>
            <asp:DropDownList ID="DropDownList1"
             DataSource='<%#Eval("Pages") %>'
             SelectedValue='<%#Bind("PageID") %>'
             DataTextField="Url"
             DataValueField="PageID"
             runat="server">
            </asp:DropDownList>
        </ItemTemplate>
        </asp:TemplateField>           
    </Columns>
</asp:GridView>
    <asp:LinqDataSource ID="LinqDataSource1" runat="server" ContextTypeName="ManyToMany.UserPageDataContext"
        EntityTypeName="" TableName="UserPages">
    </asp:LinqDataSource>
</asp:Content>

3 个答案:

答案 0 :(得分:1)

好吧,我似乎找到了答案。此页面解释了多对多关系和LINQ:http://blogs.msdn.com/b/mitsu/archive/2007/06/21/how-to-implement-a-many-to-many-relationship-using-linq-to-sql.aspx的问题。使用该信息,我可以修改User类,使其具有返回IEnumerable集合的属性。我将它添加到User类(在Linq上下文的代码隐藏中):`

    public IEnumerable<Page> Pages
    {
        get { return UserPages.Select(u => u.Page); }
    }

这样我可以拥有多对多关系,我可以直接在aspx中引用新的Pages属性:

    <%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="ManyToMany._Default" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title></title>
</head>
<body>
    <form id="form1" runat="server">
    <div>
        <asp:GridView ID="GridView2" runat="server" DataSourceID="LinqDataSourceUsers" AutoGenerateColumns="false">
            <Columns>
                <asp:CommandField ShowSelectButton="True" />
                <asp:BoundField DataField="UserID" HeaderText="UserID" />
                <asp:BoundField DataField="Name" HeaderText="Name" />
                <asp:TemplateField HeaderText="Pages">
                    <ItemTemplate>
                        <asp:DropDownList ID="DropDownList1" DataSource='<%#Eval("Pages") %>' DataTextField="Url"
                            runat="server">
                        </asp:DropDownList>
                    </ItemTemplate>
                </asp:TemplateField>
            </Columns>
        </asp:GridView>
        <asp:LinqDataSource ID="LinqDataSourceUsers" runat="server" ContextTypeName="ManyToMany.UserPageDBDataContext"
            TableName="Users">
        </asp:LinqDataSource>
    </div>
    </form>
</body>
</html>

我希望这能帮助那些一直在努力解决这个问题的人!

答案 1 :(得分:0)

尝试将DropDownList DataSource绑定到用户对象的Pages属性

<asp:GridView ID="GridView1" runat="server" DataSourceID="LinqDataSourceUsers" AutoGenerateColumns="false">
    <Columns>
        <asp:CommandField ShowSelectButton="True" />
        <asp:BoundField DataField="UserID" HeaderText="UserID" />
        <asp:BoundField DataField="Name" HeaderText="Name" />
        <asp:BoundField DataField="PageID" HeaderText="PageID" />
        <asp:TemplateField HeaderText="Pages">
        <ItemTemplate
            <asp:DropDownList ID="DropDownList1"
             DataSource='<%#Eval("Pages") %>'
             SelectedValue='<%#Bind("PageID") %>'
             DataTextField="Url"
             DataValueField="PageID"
             runat="server">
            </asp:DropDownList>
        </ItemTemplate>
        </asp:TemplateField>           
    </Columns>
</asp:GridView>

答案 2 :(得分:0)

我之前遇到类似情况的ListView和LinqDataSources。我发现的唯一解决方案是在OnRowCreated或OnRowDatabound事件中设置DropDownlist的数据源。

您仍然可以将LinqDataSource用于BoundFields,但我怀疑在这种情况下您可能需要在后面的代码中执行TemplateField。

代码:

<asp:GridView ID="GridView1" runat="server" OnRowCreated="GridView1_OnRowCreated" DataSourceID="LinqDataSource1" AutoGenerateColumns="false">
<Columns>
    <asp:CommandField ShowSelectButton="True" />
    <asp:BoundField DataField="UserID" HeaderText="UserID" />
    <asp:BoundField DataField="Name" HeaderText="Name" />
    <asp:BoundField DataField="PageID" HeaderText="PageID" />
    <asp:TemplateField HeaderText="Pages">
    <ItemTemplate>
        <asp:DropDownList ID="DropDownList1"
         DataSource='<%#Eval("Pages") %>'
         SelectedValue='<%#Bind("PageID") %>'
         DataTextField="Url"
         DataValueField="PageID"
         runat="server">
        </asp:DropDownList>
    </ItemTemplate>
    </asp:TemplateField>           
</Columns>

C#:

protected void GridView1_OnRowCreated(object sender, EventArgs e)
{
   //Create int variable with the UserId value
   //Create new Linq query to be used as datasource.  must get pages and filter by userid.
   //FindControl DropDownList1
   //use the linq query mentioned in the second comment  as the datasource for DropDownList1
   //DataBind DropDownList1

   //Example: 
int userId = /*get userid logic*/;
var userPages = from t in dc.Pages
                where t.UserId = userId
                select t;
((DropDownList)/*Find drop down list*/).DataSource = userPages;
((DropDownList)/*Find drop down list*/).DataBind()
}