在 C# 中生成动态表内容

发布于 2024-12-14 04:44:13 字数 2298 浏览 1 评论 0原文

我在创建以下内容时遇到了一些挑战:

我需要在 ASP.NET 中基于 xml 内容生成许多固定大小的 2 列和 4 行表。所以我的 html 容器是一个固定大小的 2 列 x 4 行表格的倍数。在每个表中,每列将保存 xml 中的一个 [item],其中该列的顶部单元格是 [category] ​​标记,下面的 3 个单元格保存 [make#] 标记;因此,该列中总共 4 行,每个 [make#] 对应一个。所以一个 Table 可以容纳 2 个 [item] ;每列一个。

假设我的源来自 XML 文件:

<items>
<item>
<category>Cat 1</category>
<make1>101</make1>
<make2>102</make2>
<make3>103</make3>
</item>
<item>
<category>Cat 2</category>
<make1>201</make1>
<make2>202</make2>
<make3>203</make3>
</item>
<item>
<category>Cat 3</category>
<make1>301</make1>
<make2>302</make2>
<make3>303</make3>
</item>
<item>
<category>Cat 4</category>
<make1>401</make1>
<make2></make2>
<make3></make3>
</item>
<item>
<category>Cat 5</category>
<make1>501</make1>
<make2>502</make2>
<make3</make3>
</item>
</items>

并且我想要的 5 个类别的输出(其中每个类别在 html 中最多可以有 3 个项目)是:

<table> 
<tr> <td>Cat 1</td> <td>Cat 2</td> </tr> 
<tr> <td>101</td> <td>201</td> </tr> 
<tr> <td>102</td> <td>202</td> </tr> 
<tr> <td>103</td> <td>203</td> </tr> 
</table>
<table> 
<tr> <td>Cat 3</td> <td>Cat 4</td> </tr> 
<tr> <td>301</td> <td>401</td> </tr> 
<tr> <td>302</td> <td>&nbsp;</td> </tr> 
<tr> <td>303</td> <td>&nbsp;</td> </tr> 
</table>
<table> 
<tr> <td>Cat 5</td> <td>&nbsp;</td> </tr> 
<tr> <td>501</td> <td>&nbsp;</td> </tr> 
<tr> <td>502</td> <td>&nbsp;</td> </tr> 
<tr> <td>&nbsp;</td> <td>&nbsp;</td> </tr> 
</table>

我将如何实现这一点?

请注意,我需要表格,因为我正在使用带有具有该结构的硬编码轮播的轮播......

I'm having a bit of a challenge to create the following:

I need to generate a number of fixed sized tables of 2 columns and 4 rows in ASP.NET based on an xml content. So my html container is a multiple of table with a fixed sized 2 columns by 4 rows. In each table, each column will hold an [item] from the xml, where the top cell in the column is the [category] tag, and the 3 cells underneath holds the [make#] tags; so one for each [make#] for a total of 4 rows in the column. So a Table can hold 2 [item] ; one for each column.

Assuming my source is from an XML file:

<items>
<item>
<category>Cat 1</category>
<make1>101</make1>
<make2>102</make2>
<make3>103</make3>
</item>
<item>
<category>Cat 2</category>
<make1>201</make1>
<make2>202</make2>
<make3>203</make3>
</item>
<item>
<category>Cat 3</category>
<make1>301</make1>
<make2>302</make2>
<make3>303</make3>
</item>
<item>
<category>Cat 4</category>
<make1>401</make1>
<make2></make2>
<make3></make3>
</item>
<item>
<category>Cat 5</category>
<make1>501</make1>
<make2>502</make2>
<make3</make3>
</item>
</items>

and my desired output for the 5 categories where each category can have up to 3 items underneath in html is:

<table> 
<tr> <td>Cat 1</td> <td>Cat 2</td> </tr> 
<tr> <td>101</td> <td>201</td> </tr> 
<tr> <td>102</td> <td>202</td> </tr> 
<tr> <td>103</td> <td>203</td> </tr> 
</table>
<table> 
<tr> <td>Cat 3</td> <td>Cat 4</td> </tr> 
<tr> <td>301</td> <td>401</td> </tr> 
<tr> <td>302</td> <td> </td> </tr> 
<tr> <td>303</td> <td> </td> </tr> 
</table>
<table> 
<tr> <td>Cat 5</td> <td> </td> </tr> 
<tr> <td>501</td> <td> </td> </tr> 
<tr> <td>502</td> <td> </td> </tr> 
<tr> <td> </td> <td> </td> </tr> 
</table>

How would I achieve this?

Note I need tables because I'm using a carousel with a hard coded carousel with that structure...

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

尽揽少女心 2024-12-21 04:44:13

经过一番讨论,我认为我们得出的结论是,中继器方法不是最好的路线。这里的基本问题是如何并排输入两个实体。有一个为此构建的 ASP.NET 控件:DataList。

使用DataList,您可以设置重复项目的最大数量以及重复项目的方向(水平/垂直)。

因此,您需要将以下 DataList 代码添加到您的 aspx 页面中:

<asp:DataList ID="DataList1" runat="server" DataSourceID="XmlDataSource1" RepeatColumns="2" RepeatDirection="Horizontal">
    <HeaderTemplate>Items</HeaderTemplate>
    <ItemTemplate>
        <table border=1>
            <tr>
                <td>
                    <%# XPath("category")%>
                </td>
            </tr>
            <tr>
                <td>
                    <%# XPath("make1")%>
                </td>
            </tr>
            <tr>
                <td>
                    <%# XPath("make2")%>
                </td>
            </tr>
            <tr>
                <td>
                    <%# XPath("make3")%>
                </td>
            </tr>
        </table>

    </ItemTemplate>
</asp:DataList>

这里的关键是每个项目的数据都绑定在 中。然后,DataList 本身负责根据标志 RepeatColumns="2"RepeatDirection="Horizo​​ntal" 排列每个项目。

一些快速的 魔法:

<asp:XmlDataSource ID="XmlDataSource1" runat="server" 
    XPath="//items/item">
</asp:XmlDataSource>

其中 XPath="//items/item" 将 XmlDataSource 指向 xml 中每个实体的位置。它通过 DataList 本身上的以下标记绑定到 DataList: DataSourceID="XmlDataSource1"

在代码隐藏文件中,我作了作弊,只是将 XML 作为字符串提供:

 this.XmlDataSource1.Data = @";
                                  <项目>
                                      <类别>类别 1
                                      101
                                      102
                                      103
                                  
                                  <项目>
                                      <类别>类别 2
                                      201
                                      202
                                      203
                                  
                                  <项目>
                                      <类别>类别 3
                                      301
                                      302
                                      303
                                  
                                  <项目>
                                      <类别>类别 4
                                      401
                                      
                                      
                                  
                                  <项目>
                                      <类别>Cat 5
                                      501
                                      502
                                      
                                  
                                  ";

她工作了!

顺便说一句,我永远不会原谅你缺少“>”在您原始帖子的 XML 中。找到它让我发疯。 :)

现在,假设理想情况下完成所有这些操作的最佳方法是将 xml 反序列化为 .NET 类并以正确的方式绑定所有内容(即:数据的代码隐藏绑定等),但总体思路是这样的。

关于嵌套表问题的OP评论:

GridList有一个名为RepeatLayout的属性。将此属性设置为 RepeatLayout.Flow 将使用其他元素而不是表。来自 MSDN:

显示的项目没有表结构。渲染的标记由 span 元素组成,项目由 br 元素分隔。 此处每个枚举的布局

另外,本文还讨论了 DataGrid、DataList 和 Repeater 之间的区别 MSDN

旧答案:

我正在考虑接受两个项目实体作为参数的用户控件。

因此,如果您有一个名为 Item: 的类,

public class Item
{
    public string Category{get;set;}
    public List<string> Makes { get; set; }
}

并且您的 UserControl 如下所示:
(ASPX)

<table> 
<tr>
    <td><asp:Label ID="lblCategory1" runat="server" /></td>
    <td><asp:Label ID="lblCategory2" runat="server" /></td>
</tr> 
<asp:Repeater ID="rptMakes" runat="server">
    <HeaderTemplate><tr></tr></HeaderTemplate>
    <ItemTemplate>
        <td>
        <asp:Label ID="lblMake1" runat="server" />
        </td>
        <td>
        <asp:Label ID="lblMake2" runat="server" />
        </td>
    </ItemTemplate>
    <SeparatorTemplate></tr><tr></SeparatorTemplate>
    <FooterTemplate>
        </tr>
    </FooterTemplate>
</asp:Repeater>
</table>

并在 .cs 页面上像这样:

private Item Item2;

protected override void OnInit(EventArgs e)
{
    this.rptMakes.ItemDataBound += new RepeaterItemEventHandler(rptMakes_ItemDataBound);
    base.OnInit(e);
}

void rptMakes_ItemDataBound(object sender, RepeaterItemEventArgs e)
{
    if (e.Item.ItemType == ListItemType.Item || e.Item.ItemType == ListItemType.AlternatingItem)
    {
        ((Label)e.Item.FindControl("lblMake1")).Text = e.Item.DataItem.ToString();
        if (this.Item2 != null)
        {
            ((Label)e.Item.FindControl("lblMake2")).Text = this.Item2.Makes[e.Item.ItemIndex];
        }
        else
        {
            ((Label)e.Item.FindControl("lblMake2")).Text = " ";
        }
    }
}

protected void Page_Load(object sender, EventArgs e)
{

}
public void Populate(Item item1, Item item2)
{
    this.lblCategory1.Text = item1.Category;
    if (item2 != null)
    {
        this.lblCategory2.Text = item2.Category;
    }
    else
    {
        this.lblCategory2.Text = " ";
    }
    this.Item2 = item2;
    this.rptMakes.DataSource = item1.Makes;
    this.rptMakes.DataBind();
}

从那里,只需迭代 aspx 页面上的原始 Item 实体列表并将每两个实体传递到 UC 即可。

After some discussion I think we came to the conclusion that the repeater method is not the best route to take. The basic problem here is how to input two entities side-by-side. There is an asp.net control built for this: the DataList.

With the DataList, you can set the maximum number of items to repeat as well as the direction to repeat the items (Horizontal / Vertical).

So, with that, you will want to add the following DataList code to your aspx page:

<asp:DataList ID="DataList1" runat="server" DataSourceID="XmlDataSource1" RepeatColumns="2" RepeatDirection="Horizontal">
    <HeaderTemplate>Items</HeaderTemplate>
    <ItemTemplate>
        <table border=1>
            <tr>
                <td>
                    <%# XPath("category")%>
                </td>
            </tr>
            <tr>
                <td>
                    <%# XPath("make1")%>
                </td>
            </tr>
            <tr>
                <td>
                    <%# XPath("make2")%>
                </td>
            </tr>
            <tr>
                <td>
                    <%# XPath("make3")%>
                </td>
            </tr>
        </table>

    </ItemTemplate>
</asp:DataList>

The key here is that each item's data is bound in the <ItemTemplate>. Then the DataList itself takes care of arranging each item according to the flags RepeatColumns="2" and RepeatDirection="Horizontal".

Some quick <asp:XmlDataSource> magic:

<asp:XmlDataSource ID="XmlDataSource1" runat="server" 
    XPath="//items/item">
</asp:XmlDataSource>

Where XPath="//items/item" points the XmlDataSource to the location of each entity in the xml. This is bound to the DataList with the following tag on the DataList itself: DataSourceID="XmlDataSource1"

On the code-behind file I cheated and just fed the XML as a string:

  this.XmlDataSource1.Data = @"<items>
                                  <item>
                                      <category>Cat 1</category>
                                      <make1>101</make1>
                                      <make2>102</make2>
                                      <make3>103</make3>
                                  </item>
                                  <item>
                                      <category>Cat 2</category>
                                      <make1>201</make1>
                                      <make2>202</make2>
                                      <make3>203</make3>
                                  </item>
                                  <item>
                                      <category>Cat 3</category>
                                      <make1>301</make1>
                                      <make2>302</make2>
                                      <make3>303</make3>
                                  </item>
                                  <item>
                                      <category>Cat 4</category>
                                      <make1>401</make1>
                                      <make2></make2>
                                      <make3></make3>
                                  </item>
                                  <item>
                                      <category>Cat 5</category>
                                      <make1>501</make1>
                                      <make2>502</make2>
                                      <make3></make3>
                                  </item>
                                  </items>";

And she works!

BTW, I'll never forgive you for the missing ">" in the XML of your original post. Drove me nuts finding it. :)

Now, granted that ideally the best method to do all this is deserializing the xml into .NET classes and binding everything the proper way (ie: code-behind binding of data, etc), but the general idea is there.

Regarding OP comment about nested table issue:

The GridList has a property called RepeatLayout. Setting this property to RepeatLayout.Flow will use other elements rather than tables. From MSDN:

Items are displayed without a table structure. Rendered markup consists of a span element and items are separated by br elements. Layouts for each enum here

Also, this article discusses the differences between the DataGrid, DataList and Repeater MSDN

OLD ANSWER:

I'm thinking along the lines of a Usercontrol that accepts two item entities as parameters.

So if you have a class called Item:

public class Item
{
    public string Category{get;set;}
    public List<string> Makes { get; set; }
}

And your UserControl looks like this:
(ASPX)

<table> 
<tr>
    <td><asp:Label ID="lblCategory1" runat="server" /></td>
    <td><asp:Label ID="lblCategory2" runat="server" /></td>
</tr> 
<asp:Repeater ID="rptMakes" runat="server">
    <HeaderTemplate><tr></tr></HeaderTemplate>
    <ItemTemplate>
        <td>
        <asp:Label ID="lblMake1" runat="server" />
        </td>
        <td>
        <asp:Label ID="lblMake2" runat="server" />
        </td>
    </ItemTemplate>
    <SeparatorTemplate></tr><tr></SeparatorTemplate>
    <FooterTemplate>
        </tr>
    </FooterTemplate>
</asp:Repeater>
</table>

and like this on the .cs page:

private Item Item2;

protected override void OnInit(EventArgs e)
{
    this.rptMakes.ItemDataBound += new RepeaterItemEventHandler(rptMakes_ItemDataBound);
    base.OnInit(e);
}

void rptMakes_ItemDataBound(object sender, RepeaterItemEventArgs e)
{
    if (e.Item.ItemType == ListItemType.Item || e.Item.ItemType == ListItemType.AlternatingItem)
    {
        ((Label)e.Item.FindControl("lblMake1")).Text = e.Item.DataItem.ToString();
        if (this.Item2 != null)
        {
            ((Label)e.Item.FindControl("lblMake2")).Text = this.Item2.Makes[e.Item.ItemIndex];
        }
        else
        {
            ((Label)e.Item.FindControl("lblMake2")).Text = " ";
        }
    }
}

protected void Page_Load(object sender, EventArgs e)
{

}
public void Populate(Item item1, Item item2)
{
    this.lblCategory1.Text = item1.Category;
    if (item2 != null)
    {
        this.lblCategory2.Text = item2.Category;
    }
    else
    {
        this.lblCategory2.Text = " ";
    }
    this.Item2 = item2;
    this.rptMakes.DataSource = item1.Makes;
    this.rptMakes.DataBind();
}

From there it is just a matter of iterating over the original list of Item entities on your aspx page and passing out every two entities to a UC.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文