Groups | Blog | Home
all groups > asp.net datagrid control > november 2005 >

asp.net datagrid control : Repeating horizontally


Owen Blacker
11/4/2005 11:25:31 AM
Bear with me, this query isn't fun.

I'm building an e-commerce site and the Information Architecture for
the
Product Comparison page requires repeating horizontally:


+----------+--------------+--------------+--------------+--------------+
| | [Image] | [Image] | [Image] | [Image]
|
| | | | |
|
| | Product name | Product name | Product name | Product
name |
| | as hyperlink | as hyperlink | as hyperlink | as
hyperlink |
| | | | |
|
| | Price | Price | Price | Price
|
| | | | |
|
| | Description | Description | Description |
Description |

+----------+--------------+--------------+--------------+--------------+
| Product specifications (colspanned)
|

+----------+--------------+--------------+--------------+--------------+
| Weight | #### kg | #### kg | #### kg | #### kg
|

+----------+--------------+--------------+--------------+--------------+
| Material | Blah blah | Blah blah | Blah blah | Blah blah
|

+----------+--------------+--------------+--------------+--------------+
| Another | Blah blah | Blah blah | Blah blah | Blah blah
|
| detail | blah blah | blah blah | blah blah | blah blah
|

+----------+--------------+--------------+--------------+--------------+

where the number of products being compared is variable. (To
complicate
matters further, I don't necessarily know what the row headers on the
left
are either, as they vary by product type, but that's another issue and
isn't why I'm mailing the list.)

Now the data need to be in a table, obviously, but can't be in more
than
one table, as that would completely destroy the accessibility of the
page.

I can't see how I could use a regular Repeater control, as the
ItemTemplate
can't contain <tr> or </tr> tags (which would cause each product-column
to
scroll *down* the page, rather than *across* it.

I can't see how I could use a DataGrid, as the first row contains much
more
complex data (an image, a hyperlink, some text and so on).

Does anyone have *any* ideas on how I might databind my source to
*something*
so this might work?

All suggestions greatly appreciated. If people could cc: me on any
replies,
so I notice them that little quicker, that would be even better.

Thanks, everyone,


Owen Blacker
--
Owen Blacker
Senior Software Developer

Wheel: insight | thinking | creativity

owen.blacker@wheel.co.uk www.wheel.co.uk
mos2128
11/5/2005 2:58:02 PM
here if you like to use datagrid to show many items in one column you have to
use Template column, that well be more easy when you add it from the property
builder of the datagrid and after that you right click on the datagrid and
choose edit tamplate so that will help you to see how you can edit it as you
like for that column. here i will send you the html code for a datagrid that
i used befor, so you can see in the last template column how to add more
controls at the same time.
<asp:datagrid id="DataGrid1" runat="server" DataKeyField="forum_ID"
BorderWidth="1px" BorderColor="Black"
AutoGenerateColumns="False" Width="100%">
<AlternatingItemStyle BackColor="White"></AlternatingItemStyle>
<ItemStyle BackColor="#CCCCFF"></ItemStyle>
<HeaderStyle Font-Italic="True" Font-Bold="True" ForeColor="White"
BackColor="#000066"></HeaderStyle>
<Columns>
<asp:TemplateColumn HeaderText="Kategori">
<HeaderStyle Width="50%"></HeaderStyle>
<ItemTemplate>
<asp:LinkButton id=LinkButton2 runat="server" Text='<%#
DataBinder.Eval(Container, "DataItem.forum_adi") %>' Font-Bold="True"
Font-Italic="True" CommandName="forum_adi_link">
</asp:LinkButton><BR>
<asp:Label id=Label1 runat="server" Text='<%#
DataBinder.Eval(Container, "DataItem.forum_aciklama") %>' Font-Bold="True">
</asp:Label>
</ItemTemplate>
</asp:TemplateColumn>
<asp:BoundColumn DataField="mesaj_sayisi" HeaderText="Mesaj Sayısı">
<HeaderStyle HorizontalAlign="Center" Width="10%"></HeaderStyle>
<ItemStyle Font-Bold="True" HorizontalAlign="Center"
VerticalAlign="Middle"></ItemStyle>
</asp:BoundColumn>
<asp:BoundColumn DataField="cevap_sayisi" HeaderText="Cevap Sayısı">
<HeaderStyle HorizontalAlign="Center" Width="10%"></HeaderStyle>
<ItemStyle Font-Bold="True" HorizontalAlign="Center"
VerticalAlign="Middle"></ItemStyle>
</asp:BoundColumn>
<asp:TemplateColumn HeaderText="Son Gönderilen">
<HeaderStyle HorizontalAlign="Center" Width="30%"></HeaderStyle>
<ItemStyle Font-Bold="True" Wrap="False" HorizontalAlign="Center"
VerticalAlign="Middle"></ItemStyle>
<ItemTemplate>
<asp:HyperLink id=HyperLink2 runat="server" Text='<%#
DataBinder.Eval(Container, "DataItem.enbuyuk") %>'>
</asp:HyperLink>
<asp:ImageButton id="Imgbtnmsj" runat="server"
ImageUrl="images/msgyaz.gif"></asp:ImageButton><BR>
<asp:Label id="Label2" runat="server" Font-Bold="True">Gönderen
:</asp:Label>
<asp:HyperLink id=HyperLink3 runat="server" Text='<%#
DataBinder.Eval(Container, "DataItem.nick") %>' NavigateUrl='<%#
DataBinder.Eval(Container, "DataItem.forum_ID",
"Kategorigoster.aspx?forum_ID={0}") %>'>
</asp:HyperLink>
</ItemTemplate>
</asp:TemplateColumn>
</Columns>
</asp:datagrid>
--
PLEASE DO NOT FORGET TO RATE THE ANSWER
happy coding
Muhanad YOUNIS
MCSD.NET / MCT


[quoted text, click to view]
Owen Blacker
11/8/2005 6:09:51 AM
Thanks to both of you for your replies, though neither of them quite
hit the spot.

I can't use a DataGrid, even with TemplateColumns, because I don't know
how many properties there will be down the left-hand side (it's
dependent on product type). Equally, my columns all need the same
template (apart from the header column) -- it's the rows that are the
formatting problem. If you look again at the diagram I drew, you'll
see that (apart from the header column) every column represents one
product, with consistent formatting across the columns; the problem is
that the first cell needs to be very different to the others. And the
second row is one cell, rowspanned across the full row.

Inverting the DataTable might well be of some use to me (and thank you
very much for sharing the code), but rearranging the data wasn't the
intrinsically difficult part; displaying it was.

In the end, one of my colleagues came up with the idea that seems to
have worked -- to use a Table control and mess with the cells
programatically.

I've simplified it, removed lots of the error-handling and complicated
details that weren't relevant to my query and so on, but this is
roughly what I ended up writing (in C#) yesterday:

string[] productIDs = Request.QueryString["p"].Split(',');

ProductCatalog catalog = Microsoft.CommerceServer.Runtime.
CommerceContext.Current.CatalogSystem.GetCatalog(...);

...

#region TableRow row0
TableRow row0 = new TableRow();
CompareTable.Rows.Add(row0);
row0.Cells.Add(new TableCell()); // Empty leftmost cell
#endregion

#region TableRow specsRow
TableRow specsRow = new TableRow();
TableCell specsCell = new TableCell();
Label specsLabel = new Label();
specsLabel.Text = "Specifications";
specsCell.Controls.Add(specsLabel);
specsCell.ColumnSpan = productIDs.Length + 1;
specsRow.Cells.Add(specsCell);
CompareTable.Rows.Add(specsRow);
#endregion

#region TableRow rowN
TableRow rowN = new TableRow();
CompareTable.Rows.Add(rowN);
rowN.Cells.Add(new TableCell());
#endregion

#region Loop through all products...
bool rowHeadersSet = false;
foreach (string productID in productIDs)
{
Trace.Write("Compare", "Inspecting product " + productID
+ "...");

DataRow properties = catalog.GetProduct(productID
).GetProductProperties().Tables[0].Rows[0];
string type = properties["DefinitionName"].ToString();

if (_productType == null)
_productType = type;
else if (_productType != type)
throw new CatalogException(
"Cannot compare products of different types");

string productLink = "~/Product.aspx?CS_ProductID=" + ...;

#region TableCell cell0
TableCell cell0 = new TableCell();

#region HyperLink img
HyperLink img = new HyperLink();
img.NavigateUrl = productLink;
img.ToolTip = properties["DisplayName"].ToString();
img.ImageUrl = ...;
img.CssClass = "compareImage";
cell0.Controls.Add(LiteralOpenPara);
cell0.Controls.Add(img);
cell0.Controls.Add(LiteralClosePara);
#endregion

#region HyperLink name
HyperLink name = new HyperLink();
name.NavigateUrl = productLink;
name.Text = properties["DisplayName"].ToString();
name.CssClass = "compareProductName";
cell0.Controls.Add(LiteralOpenPara);
cell0.Controls.Add(name);
cell0.Controls.Add(LiteralClosePara);
#endregion

#region Label price
Label price = new Label();
price.Text = GenericUtilities.FormatPrice(
(decimal) properties["cy_list_price"]);
price.CssClass = "comparePrice";
cell0.Controls.Add(price);
#endregion

#region Label desc
Label desc = new Label();
desc.Text = properties["Product Intro"].ToString();
desc.CssClass = "compareDesc";
cell0.Controls.Add(desc);
#endregion

#region HyperLink removeLink
HyperLink removeLink = new HyperLink();
removeLink.NavigateUrl = GetRemoveLink(productID);
removeLink.Text = "Remove";
removeLink.CssClass = "compareRemoveLink";
cell0.Controls.Add(LiteralOpenPara);
cell0.Controls.Add(removeLink);
cell0.Controls.Add(LiteralClosePara);
#endregion

row0.Cells.Add(cell0);
#endregion

#region Other cells...
#region string[] keyNames
string[] keyNames = AppSettings.GetCommonSettings(
"ProductSpecs." + _productType).Split(';');

if (!rowHeadersSet)
{
for (int i = 0; i < keyNames.Length; i++)
{
TableRow r = new TableRow();
TableHeaderCell c = new TableHeaderCell();
c.Text = keyNames[i];
c.Attributes["scope"] = "row";
r.Cells.Add(c);
CompareTable.Rows.Add(r);
}

rowHeadersSet = true;
}
#endregion

for (int i = 0; i < keyNames.Length; i++)
{
TableCell cell = new TableCell();

if (...)
{
...
}
else
cell.Text = GenericUtilities.GetNullableString(
properties[keyNames[i]]);

Trace.Write("Compare", "Now adding cell " + (i+2)
+ " of " + CompareTable.Rows.Count);

// Now add the cell, relying on the for loop being
// synchronised with the one inside the if
// (!rowHeadersSet) statement in the code region
// "string[] keyNames".
CompareTable.Rows[i + 2].Cells.Add(cell);
}
#endregion
}
#endregion
AddThis Social Bookmark Button