如何在asp.net webform中显示嵌套ICollection的数据

时间:2012-04-02 20:35:06

标签: asp.net entity-framework webforms

我试图找出如何将我使用EF检索到的嵌套集合绑定到asp:ListView或asp:Web表单的Repeater控件。

使用EF我创建了以下查询,其中我选择了一组代理商以及他们与其他代理商共享的实体列表。

public static ICollection<Agency> GetAllAgencies()
        {
            ICollection<Agency> retAgencies = null;
            try
            {
                using (var context = new InformSecurityEntities(string.Empty))
                {
                   // retAgencies = context.Agencies.OrderBy(a => a.AgencyName).ToList();
                    retAgencies = (from a in context.Agencies
                                  .Include("SecurityDataShares1")
                                  .OrderBy(a => a.AgencyName)
                                   select a).ToList();
                }
            }
            catch (Exception ex)
            {
                throw new Exception("Exception thrown in UserFactory.GetAllAgencies() : " + ex.InnerException + ex.Message); 
            }

            return retAgencies;
        }

我一直在控制台应用中测试它,它运行正常。在控制台中,我将结果呈现如下:

private static void showAgencies()
        {
            var results = UserFactory.GetAllAgencies();
            foreach (var item in results)
            {
                Console.WriteLine("Id: {0} || Name: {1}",
                    item.AgencyId,
                    item.AgencyName);
                foreach (var i in item.SecurityDataShares1)
                {
                    Console.WriteLine(i.ReceivingAgency.AgencyName); 
                    Console.WriteLine(convertEntityToText(i.EntityId));
                }

            }
            Console.WriteLine("enter...");
            Console.ReadLine();
        }

注意:SecurityDataShares1是ICollection

我希望能够做的是将结果渲染成webform中类似于下面的格式:

Agency 1
  Entity 1, Entity 2, Entity 3 ...
Agency 2
  Entity 1, Entity 4, Entity 5 ...

我挂起的地方是在控制台应用程序中,我可以访问嵌套集合并迭代它以呈现我的结果。我尝试使用带有辅助嵌套转发器的转发器控件,并将控件绑定到方法结果。

<asp:Repeater ID="agencyListRepeater" runat="server" OnItemDataBound="mainRepeaterBound">
                <ItemTemplate>
                    <div class="itemsRow">
                    <div class="column-holder">
                    <asp:Label CssClass="mgmtResultText" ID="lbl_AgencyName" runat="server" Text='<%# Eval("AgencyName") %>' /></div>
                    <br />
                    <div class="mgmtIndentDiv">Sharing data with the following agencies:</div>
                      <asp:Repeater id="nestedDataShare" runat="server">
                      <ItemTemplate>
                      <asp:Label runat="server" Text='<%# Eval("SecurityDataShares1.AgencyName") %>' />
                      <asp:Label runat="server" Text='<%# Eval("SecurityDataShares1.EntityId") %>' />
                      </ItemTemplate>

                      </asp:Repeater>
                    </div>
                </ItemTemplate>
            </asp:Repeater>

背后的代码

   if (userRole.IsSysAdmin)
   {
    var agencyData = UserFactory.GetAllAgencies();

    if (agencyData != null || agencyData.Count > 0)
    {
      agencyListRepeater.DataSource = agencyData;
      agencyListRepeater.DataBind();
    }
   else
   ...

但是,只要SecurityDataShares1为null,这就会失败。

对此有何建议或最佳方法?

提前致谢。

3 个答案:

答案 0 :(得分:0)

在mainRepeaterBound函数中,您可以获得对代理实体集合的引用。

    public void mainRepeaterBound(object sender, RepeaterItemEventArgs  e)
    {
        if (e.Item.ItemType == ListItemType.Item)
        {
            System.Web.UI.WebControls.Repeater nestedDataShare = (System.Web.UI.WebControls.Repeater)e.Item.FindControl("nestedDataShare");
            Agency item = (Agency)e.Item.DataItem;
            nestedDataShare.DataSource = from o in item.SecurityDataShares1 select o;
            nestedDataShare.DataBind();
        }

    }

然后你的内部转发器看起来像:

  <asp:Repeater id="nestedDataShare" runat="server">
                  <ItemTemplate>
                  <asp:Label runat="server" Text='<%# Eval("AgencyName") %>' />
                  <asp:Label runat="server" Text='<%# Eval("EntityId") %>' />
                  </ItemTemplate>
   </asp:Repeater>

所以现在你没有通过可能不存在的对象访问属性。

答案 1 :(得分:0)

Eval语句也可用于设置 DataSource 属性。嵌套转发器将具有 SecurityData Shares 列表中使用的类型的Eval语句。

 <asp:Repeater ID="nestedDataShare" 
             runat="server" 
             DataSource='<%# Eval("SecurityDataShares1")'>

     <ItemTemplate>
         <asp:Label runat="server" Text='<%# Eval("AgencyName") %>' />
         <asp:Label runat="server" Text='<%# Eval("EntityId") %>' />
     </ItemTemplate>

</asp:Repeater>

答案 2 :(得分:0)

我从来没有能够让嵌套的阅读器呈现数据,而它会编译,零(0)结果总是在嵌套对象上返回。结果我找到了另一种解决方案。 请记住,这更像是解决在UI中呈现数据的原始问题

我决定尝试使用LiteralControl class直接将html注入ui,而不是使用数据阅读器。为了在aspx页面中执行此操作,我添加了一个面板控件。您也可以使用属性为ruant =“server”的div元素,但我决定使用<asp:Panel/>控件:

所以在ASPX文件中我添加了以下内容:

       <asp:Panel ID="agencyList" runat="server" />

然后在我的代码后面,我创建了一个带有两个参数的方法:p = PanelName和a = Collection。

这种方法允许我遍历集合并将结果写为UI作为html。 记住LiteralControl只允许创建不需要服务器端处理的html元素或字符串。因此,如果要添加服务器端控件,则需要使用单独的方法来创建对象{{ 3}}

protected void CreateHtmlResults(System.Web.UI.WebControls.Panel p,  ICollection<Agency> a)
    {
        var results = a;
        foreach (var item in results)
        {
            p.Controls.Add(new LiteralControl("<p><b>" + item.AgencyName + "</b></p>"));
            foreach (var i in item.SecurityDataShares1)
            {
                p.Controls.Add(new LiteralControl(i.ReceivingAgency.AgencyName + " " + i.EntityId +"<br/>"));
            }
        }
    }

然后以如下格式调用它:

if (userRole.IsSysAdmin)
  {
  //get a list of all agencies
  agencyData = UserFactory.GetAllAgencies();

 if (agencyData != null || agencyData.Count > 0)
 {
   CreateHtmlResults(agencyList, agencyData);                           
 }
 else
 {
    //notify UI that no agencies exist
 }
 }

我仍然感谢任何其他想法或方法,否则我希望这会有所帮助。

-cheers!