0

我有一个复杂的对象,其中包含需要绑定到中继器/显示在表格中的对象的嵌套集合。对象显示 14 项:

在此处输入图像描述

我想这样显示数据:

在此处输入图像描述

对象看起来像:

在此处输入图像描述

我需要在表/列标题中显示“FieldName”,在表行中显示“FieldValue”。注意项目 3 和 5 都是“电话号码”字段名称。所以我需要 PhoneNumber 显示一次(在列标题中),然后会有 2 行显示 2 个 phonenumber FieldValues(如表格截图中)。所以集合中可能有多组项目..例如N个联系人等。我不确定如何设置中继器(或使用多少)和/或如何设置中继器OnItemDataBound。任何指向正确方向的想法或伪代码都会非常有帮助。

更新: 调用 API 响应返回列表(即联系人)

属性对象(示例):

第一项:FieldName = "Name" FieldValue = "Mike Jones"

第二项:FieldName = "电话号码" FieldValue = "999-999-9999"

第三项:FieldName = "Address" FieldValue = "123 Main St"

第 4 项:FieldName = "Name" FieldValue = "Mary Price"

第 5 项:FieldName = "电话号码" FieldValue = "888-999-7777"

第 6 项:FieldName = "Address" FieldValue = "789 Broadway St"

标记需要显示表格:

-------------------------------------------------
|Name       |   Phone Number |  Address         |
-------------------------------------------------
|Mike Jones |   999-999-9999 |  123 Main St     |
-------------------------------------------------
|Mary Price |   888-999-7777 |  789 Broadway St |
-------------------------------------------------
4

1 回答 1

1

Ok, so the question is simple this:

I have a list of names, and for each name, I may have a child table of phone numbers. They might have no phone numbers, they might have 5 phone numbers.

What is a good way to display this master reocrd, and then a repeating child record for each row?

There are LOT of ways to do this. I would often suggest that for the main display of rows, we use a listview, and then nest for the child rows a gridview.

However, as always, which road will depend on how much data, and how many rows (complex) the child data display has to be?

But, lets go with a simple grid. As such a setup becomes more complex, then I STRONG suggest going with a listview. The listview is better since it FAR more flexiblilty in terms of layout. and while the "set up" is a bit more markup, adding new columns and complex controls for each row is MUCH better. In the long run the listview in fact can wind up being less overall markup.

However, we only have two extra columns of "child repeating" data.

So we have in effect this:

 table people  - our list of contacts/people
 table Phones  - our child list of phone numbers for each "people".

So, lets whip up a grid with the table people. I will often fire up and let the wizard create that grid. I THEN blow out (delete) the data source in the web page, and then start using the delete keys to remove extra junk.

So, we now have this markup:

<div style="width:30%">
    <asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="False"
        DataKeyNames="ID" CssClass="table">
        <Columns>
            <asp:BoundField DataField="Firstname" HeaderText="Firstname"  />
            <asp:BoundField DataField="LastName" HeaderText="LastName" />
            <asp:BoundField DataField="City" HeaderText="City"  />
        </Columns>
    </asp:GridView>
</div>

And our code to fill this grid is this:

    protected void Page_Load(object sender, EventArgs e)
    {
        if (!IsPostBack)
            LoadGrid();
    }

    void LoadGrid()
    {
        DataTable rst = MyRst("SELECT * from People Order by FirstName");
        GridView1.DataSource = rst;
        GridView1.DataBind();
    }

    public DataTable MyRst(string strSQL)
    {
        DataTable rstData = new DataTable();
        using (SqlCommand cmdSQL = new SqlCommand(strSQL,
            new SqlConnection(Properties.Settings.Default.TEST4)))
        {
            cmdSQL.Connection.Open();
            rstData.Load(cmdSQL.ExecuteReader());
        }
        return rstData;
    }

And our output is this:

enter image description here

Ok, so we have this setup of course:

enter image description here

now, we could have done a query join, but then again, that would repeat the main row for each child row (and then we would have to "hide" that.

So, lets go to the markup and add the two rows. (PhoneType and PhoneNumber).

So we now have this:

<div style="width:40%">
    <asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="False"
        DataKeyNames="ID" CssClass="table">
        <Columns>
            <asp:BoundField DataField="Firstname" HeaderText="Firstname"  />
            <asp:BoundField DataField="LastName" HeaderText="LastName" />
            <asp:BoundField DataField="City" HeaderText="City"  />

            <asp:TemplateField HeaderText="Type">
                <ItemTemplate>
                    <asp:label ID="txtType" runat="server" Text = '<%# Eval("PhoneType") %>'></asp:label>
                </ItemTemplate>
            </asp:TemplateField>

            <asp:TemplateField HeaderText="Phone">
                <ItemTemplate>
                    <asp:label ID="txtPhone" runat="server" Text = '<%# Eval("Phone") %>' ></asp:label>
                </ItemTemplate>
            </asp:TemplateField>
        </Columns>  
    </asp:GridView>
</div>

(this is what I mean by using gridview - to drop in nice plane jane asp.net controls (a label in this case), you have to surround it with the itemtemplate - I find that a bit of pain if you have "lots" of columns. so if you need lots of custom columns then a list view is better. but we not too bad so far.

So, our code now becomes this: We simply pull the data for each child row, and shove the results of this child table into our two new columns we add.

this:

   void LoadGrid()
    {
        DataTable rst = MyRst("SELECT * from People Order by FirstName");

        rst.Columns.Add("PhoneType", typeof(string));
        rst.Columns.Add("Phone", typeof(string));

        foreach (DataRow OneRow in rst.Rows)
        {
            // get child rows for this main row
            DataTable ChildRows = MyRst("SELECT * from Phones where People_ID = " + OneRow["ID"]);

            foreach (DataRow ChildRow in ChildRows.Rows)
            {
                if (OneRow["PhoneType"].ToString() != "")
                {
                    // start new line in this cell
                    OneRow["PhoneType"] += "<br/>";
                    OneRow["Phone"] += "<br/>";
                }
                OneRow["PhoneType"] += ChildRow["PhoneType"].ToString();
                OneRow["Phone"] += ChildRow["PhoneNumber"].ToString();
            }
        }

        GridView1.DataSource = rst;
        GridView1.DataBind();
    }

So this was a bit of extra code to loop! In fact, in MOST cases, if we are writing looping code, then we tend to be doing this the wrong way.

We now have this:

enter image description here

And it also depends on what we want to do here. Say we needed a click button for each of the child phone numbers (maybe a email also included). So if we had to click on the child email/phone to take action, then obvious the above approach is a bit quick and dirty, but would not give us the ability to click on a particular phone number row to select.

So, say if for some reason we wanted a click event, or button to select the given child row from this display?

Then I would then move over to nesting a child grid. We would not thus need a loop to fill the child data - but in fact would bind a new grid in a simular fashion to how we built the main grid.

and as noted, I would probably jump over to a list view for the main grid.

If you wish, I can and will post a working example of a nesting a grid view inside of list view - say with a extra button to click on the child row as a "action" we might want to take.

于 2021-10-26T18:41:14.440 回答