My problem is that, in my GridView, empty cells are generated automatically. I'd like for them to not appear. I have both ShowHeaderWhenEmpty and AutoGenerateColumns at false and the same amount for TempateFields, ths and tds. Here's how it appears:
When empty, there's one empty cell above the first column.
After a PostBack, but still empty, there's empty cell that takes the entire row above.
But, when there's data, it is perfect.
I can't post images because I have not enough reputation, but I hope you still visualize and understand.
Here is my aspx code:
<asp:GridView ID="GridViewCommentaires" runat="server" ShowHeaderWhenEmpty="false"
ShowFooter="true" AutoGenerateColumns="false" BorderColor="Black">
<Columns>
<asp:TemplateField HeaderText="Date" ItemStyle-Width="100">
<ItemStyle HorizontalAlign="Center" />
<ItemTemplate>
<asp:HiddenField ID="HiddenFieldIdCommentaire" runat="server" Value='<%# Eval("[idCommentaire]") %>' />
<asp:Label ID="LabelCommentaireDate" runat="server" Text='<%# Convert.ToDateTime(Eval("dtHrEntree")).ToString("d") %>'></asp:Label>
</ItemTemplate>
<FooterTemplate>
<asp:TextBox Width="100%" runat="server" ID="TextBoxCommentaireDate" Enabled="false"
BorderStyle="None" />
</FooterTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="Entré par" ItemStyle-Width="175">
<ItemStyle HorizontalAlign="Center" />
<ItemTemplate>
<asp:Label ID="LabelCommentaireModifiePar" runat="server" Text='<%# Eval("[modifieParComplet]") %>'></asp:Label>
</ItemTemplate>
<FooterTemplate>
<asp:TextBox Width="100%" runat="server" ID="TextBoxCommentaireModifiePar" Enabled="false"
BorderStyle="None" />
</FooterTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="Commentaire" ItemStyle-Width="725">
<ItemTemplate>
<asp:Label ID="LabelCommentaire" Width="700px" runat="server" Text='<%# Eval("[commentaire]") %>'></asp:Label>
</ItemTemplate>
<FooterTemplate>
<asp:TextBox Width="100%" ID="TextBoxCommentaire" runat="server" BorderStyle="None" />
</FooterTemplate>
</asp:TemplateField>
<asp:TemplateField>
<ItemTemplate>
<asp:LinkButton ID="LinkButtonSupprimerCommentaire" CssClass="ImageSupprimer" OnClick="LinkButtonSupprimerCommentaire_Click"
Text="" ToolTip="Supprimer" runat="server" ForeColor="Transparent" Width="16px"
Height="16px" OnClientClick="return confirm('Supprimer le commentaire ?')" />
</ItemTemplate>
<FooterTemplate>
<asp:LinkButton ID="LinkButtonAjouterCommentaire" CssClass="ImageSauvegarder" OnClick="LinkButtonAjouterCommentaire_Click"
Text="" ToolTip="Ajouter" runat="server" ForeColor="Transparent" Width="16px"
Height="16px" />
</FooterTemplate>
</asp:TemplateField>
</Columns>
<EmptyDataTemplate>
<tr>
<th scope="col">
Date
</th>
<th scope="col">
Entré par
</th>
<th scope="col">
Commentaire
</th>
<th scope="col">
</th>
</tr>
<tr>
<td style="width: 100px">
<asp:TextBox Width="100%" runat="server" ID="TextBoxCommentaireDate" Enabled="false"
BorderStyle="None" />
</td>
<td style="width: 175px">
<asp:TextBox Width="100%" runat="server" ID="TextBoxCommentaireModifiePar" Enabled="false"
BorderStyle="None" />
</td>
<td style="width: 725px">
<asp:TextBox Width="100%" ID="TextBoxCommentaire" runat="server" BorderStyle="None" />
</td>
<td align="center">
<asp:LinkButton ID="LinkButtonAjouterCommentaire" CssClass="ImageSauvegarder" OnClick="LinkButtonAjouterCommentaire_Click"
ToolTip="Ajouter" runat="server" ForeColor="Transparent" Width="16px"
Height="16px" />
</td>
</tr>
</EmptyDataTemplate>
</asp:GridView>
That is very weird. I hope you can help me. Thanks in advance!
Most likely the reason for this behavior is inconsistent markup that you receive for no data. EmptyDataTemplate is used to defined the content of the row to show for empty data set:
The empty data row is displayed in a GridView control when the data source that is bound to the control does not contain any records. You can define your own custom user interface (UI) for the empty data row by using the EmptyDataTemplate property.
So what I think is happening is that your markup is inserted inside the tr tag created by the GridView, thus giving you a markup like this:
<table> <-- comes from GridView
<tr> <-- comes from GridView
<tr> <-- comes from your template
<th>...
</tr>
<tr> <-- comes from your template
<td>...
</tr>
That could easily lead to UI fluctuations.
Simple fix, although I am not 100% sure it will work, is to wrap your template in proper <table> tag:
<EmptyDataTemplate>
<table>
<tr>...
</table>
</EmptyDataTemplate>
If you have issues with the style of EmptyDataTemplate, use EmptyDataRowStyle to control its appearance:
To control the style of the empty data row, use the EmptyDataRowStyle property.
Another approach would be to rethink the way you treat no data case, perhaps hide GridView completely and show some panel with textboxes inside.
Related
I want to display records in Horizontal Layout. I used Data List control for the same which displays only 5 records.
I want select functionality so that when i click the items in Data List , complete details will be displayed in another page.
Thanks a lot.
<div style="margin-left: 25%; margin-top: 5%">
<asp:DataList ID="dlTop5" runat="server" RepeatDirection="Horizontal" RepeatLayout="Flow" RepeatColumns="5"
ItemStyle-Width="40%" >
<ItemTemplate>
<table>
<tr>
<td rowspan="3" style="margin-left: 3%">
<asp:ImageButton ID="imgServant" runat="server" ImageUrl='<%#Eval("photo")%>' Height="150px"
Width="150px" />
</td>
<td style="width: 50%">
<asp:Label ID="lblName" runat="server" Text='<%#Eval("name")%>' Font-Bold="true"
ForeColor="BlueViolet"></asp:Label>
</td>
</tr>
<tr>
<td style="width: 50%">
<asp:Label ID="lblPhone" runat="server" Text='<%#Eval("phone")%>' ForeColor="BlueViolet"> </asp:Label>
</td>
</tr>
<tr>
<td style="width: 50%">
<asp:Label ID="lblSrno" runat="server" Text='<%#Eval("sysno")%>'> </asp:Label>
</td>
</tr>
</table>
</ItemTemplate>
<FooterTemplate>
<asp:Button ID="btnViewMore" runat="server" Text="View More" />
</FooterTemplate>
</asp:DataList>
</div>
</asp:Content>
This is what I do ...
<asp:DataList ID="DataList1" runat="server" BorderColor="Black" BorderWidth="1px"
DataSourceID="SqlDataSource2" GridLines="Both" RepeatDirection="Horizontal"
ShowFooter="False" ShowHeader="False">
<ItemTemplate>
<asp:LinkButton ID="LinkButton1" runat="server" Text='<%# Eval("RollCallPeriod") %>' OnClick="LinkButton1_Click"></asp:LinkButton><br />
</ItemTemplate>
</asp:DataList><asp:SqlDataSource ID="SqlDataSource2" runat="server" ConnectionString="<%$ ConnectionStrings:ATCNTV1ConnectionString %>"
SelectCommand="SELECT RollCallPeriod FROM tblBoardingRollCallPeriods">
</asp:SqlDataSource>
And use the OnClick event to fire up a call into your code behind to reveal a panel for example and put all your specific code about the selection inside the panel - ie: Gridview, etc.
You don't have to use a LinkButton of course. It can be anything you want - a button, a hyperlink, etc
Labels do not have OnClick etc. Unless you "trap" them using JavaScript like mouseclick or mouseover.
I have a user control that has two dropdownlists, four textboxes and a gridview in said order. I want the focus to move in this order as tab key is pressed.
I have tabindex property of each control set in sequence (1005, 1010, 1015 ...) except the gridview whose tabindex property is not set to anything.
At page_load I am setting focus to the first dropdownlist.
When page is loaded, focus is on the first dropdownlist, as desired. Then when tab is pressed focus moves to the next dropdownlist, as desired. The problem is when the tab is pressed at this stage, now instead of moving to the first textbox (which has tabindex set to 1015), the focus is moved on the gridview. Note that the gridview do not have its tabindex set to anything. When tab is pressed now, the focus is moved on other user controls on the page, that is, totally out of the discussed user control. Then after several key presses user control do come back to the user control and then move in desired order, that is, first dropdownlist, then second dropdownlist, then first textbox, then second textbox, then third textbox, then fourth textbox. After this it skip the gridview altogether and move to controls which are at the master page.
So, when page is loaded, tab is moving in a different order than what it do once cycle of tabs is completed, that is, all controls are focused.
If I move focus to the first textbox by using mouse click, then press tab then focus is moved to the second textbox as desired, then to third textbox as desired, then to fourth textbox as desired.
I am using two user controls in the page, one of which is discussed above, plus a control directly on page. There are some controls in master page too.
No server or client side event handling happens when tab key is being pressed.
I have tried replace html input control with asp.net textbox control but problem remains.
Request: Please prefer a simple solution, that is one that do not require manually setting tabindex in code-behind because that is not very scalable.
<%# Control Language="C#" AutoEventWireup="true" CodeBehind="GridExpense.ascx.cs" Inherits="StationaryManagementSystem.GridExpense" %>
<%# Register Assembly="AjaxControlToolkit" Namespace="AjaxControlToolkit" TagPrefix="asp" %>
<script type="text/javascript">
function MinQuantity_Blurred()
{
$('#' + '<%= hitMaxQuantitySearch.ClientID %>')[0].value = $('#' + '<%= hitMinQuantitySearch.ClientID %>')[0].value;
}
function FromDated_Blurred()
{
$('#' + '<%= txtToDatedSearch.ClientID %>')[0].value = $('#' + '<%= txtFromDatedSearch.ClientID %>')[0].value;
}
</script>
<asp:Panel ID="panel" runat="server">
<table>
<tr>
<td>
<table width="800px">
<tr align="right">
<td class="columnOne">
Item :
</td>
<td class="columnTwo">
<asp:DropDownList ID="ddlItemSearch" runat="server" EnableViewState="true" DataValueField="Id" DataTextField="Name" TabIndex="1005" Width="200px" />
</td>
<td class="columnOne">
Officer :
</td>
<td class="columnTwo">
<asp:DropDownList ID="ddlOfficerSearch" runat="server" EnableViewState="true" DataValueField="Id" DataTextField="Name" TabIndex="1010" Width="200px" />
</td>
</tr>
<tr align="right">
<td align="right" style="width:200px">
From Quantity:
</td>
<td align="left">
<input type="text" id="hitMinQuantitySearch" name="hitMinQuantitySearch" runat="server" maxlength="9" tabindex="1015"
style="width: 90px; text-align: right" onkeydown="return isNumericKeyDown(event, false);" onkeypress="return isNumericKeyPress(event, false);"
onblur="MinQuantity_Blurred();" />
</td>
<td align="right" style="width:200px">
To Quantity:
</td>
<td align="left">
<input type="text" id="hitMaxQuantitySearch" name="hitMaxQuantitySearch" runat="server" maxlength="9" tabindex="1020"
style="width: 90px; text-align: right" onkeydown="return isNumericKeyDown(event, false);" onkeypress="return isNumericKeyPress(event, false);" />
</td>
</tr>
<tr align="right">
<td class="columnOne">
From Dated :
</td>
<td class="columnTwo">
<asp:TextBox ID="txtFromDatedSearch" runat="server" MaxLength="11" TabIndex="1025" onblur="FromDated_Blurred();" Width="90px" />
<asp:CalendarExtender ID="ceFromDatedSearch" runat="server" TargetControlID="txtFromDatedSearch" Format="dd-MMM-yyyy" />
</td>
<td class="columnOne">
To Dated :
</td>
<td class="columnTwo">
<asp:TextBox ID="txtToDatedSearch" runat="server" MaxLength="11" TabIndex="1030" Width="90px" />
<asp:CalendarExtender ID="ceToDatedSearch" runat="server" TargetControlID="txtToDatedSearch" Format="dd-MMM-yyyy" />
</td>
<td align="left">
<asp:Button ID="btnLoad" runat="server" Text="Load" TabIndex="1035" CssClass="foreRed gradientGreen cornerRound" OnClick="btnLoad_Click" />
</td>
</>
</table>
</td>
</tr>
<tr>
<td>
<asp:GridView ID="gv" runat="server" AutoGenerateColumns="False" DataSourceID="ods" AllowSorting="True" AllowPaging="True" PageSize="5"
AutoGenerateSelectButton="True" onrowcommand="gv_RowCommand" CssClass="gridSapphire" PagerStyle-CssClass="pagerSapphire"
AlternatingRowStyle-CssClass="alterSapphire" onpageindexchanged="gv_PageIndexChanged" Width="100%" EmptyDataText="List is empty."
DataKeyNames="Id" EnableViewState="true" onrowdeleted="gv_RowDeleted">
<PagerSettings Mode="Numeric"/>
<Columns>
<asp:TemplateField Visible="false">
<ItemTemplate>
<asp:Label ID="lblIdGrid" runat="server" Text='<%#Eval("Id") %>'/>
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField Visible="false">
<ItemTemplate>
<asp:Label ID="lblIdItemGrid" runat="server" Text='<%#Eval("IdItem") %>' Style="text-align:left; padding-left:5px" />
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="Item" SortExpression="NameItem" ControlStyle-Width="260px">
<ItemTemplate>
<asp:Label ID="lblNameItemGrid" runat="server" Text='<%#Eval("NameItem") %>' Style="text-align:left; padding-left:5px" />
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField Visible="false">
<ItemTemplate>
<asp:Label ID="lblIdOfficerGrid" runat="server" Text='<%#Eval("IdOfficer") %>' Style="text-align:left; padding-left:5px" />
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="Officer" SortExpression="NameOfficer" ControlStyle-Width="200px">
<ItemTemplate>
<asp:Label ID="lblNameOfficerGrid" runat="server" Text='<%#Eval("NameOfficer") %>' Style="text-align:left; padding-left:5px" />
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="Quantity" SortExpression="Quantity" ControlStyle-Width="100px">
<ItemTemplate>
<asp:Label ID="lblQuantityGrid" runat="server" Text='<%#Eval("Quantity") %>' Style="text-align:left; padding-left:5px" />
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="Dated" SortExpression="Dated" ControlStyle-Width="100px">
<ItemTemplate>
<asp:Label ID="lblDatedGrid" runat="server" Text='<%# DateTime.Parse(Eval("Dated").ToString()).ToString("dd-MMM-yyyy") %>'
Style="text-align:left; padding-left:5px" />
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField>
<ItemTemplate>
<asp:LinkButton ID="lbDeleteGrid" runat="server" CommandName="Delete" OnClientClick="return confirm('Are you sure you want to delete this Expense?')">
Delete
</asp:LinkButton>
</ItemTemplate>
</asp:TemplateField>
</Columns>
<PagerStyle CssClass="pagerSapphire" />
<AlternatingRowStyle CssClass="alterSapphire" />
</asp:GridView>
<asp:ObjectDataSource ID="ods" runat="server" TypeName="StationaryManagementSystem.Classes.DAL.Expense"
SelectMethod="Search" SelectCountMethod="CountSearch" SortParameterName="sSortExpression" EnablePaging="true"
StartRowIndexParameterName="iZeroIndexStartPage" MaximumRowsParameterName="iSizePage"
onselecting="ods_Selecting"
DeleteMethod="Delete" ondeleting="ods_Deleting">
<DeleteParameters>
<asp:Parameter Name="ID" Type="Int64" />
</DeleteParameters>
</asp:ObjectDataSource>
</td>
</tr>
</table>
</asp:Panel>
The problem is not with GridView but with a javascript library select2 that I been using but not showed above. Once this is removed the tab ordering is working almost as desired.
Some problem remains. Now the tab moves correctly through the six controls: the two dropdownlists and the four textboxes, but after that do not go to the gridview. Setting tabindex on gridview do not solve this problem.
Since problem turns out to be different than discussed in this post, I have a separate question for that here.
As said above, some of the problem discussed here still remains. Can anybody tell what is the default tabindex of controls inside a gridview if tabindex of gridview is not set. Tab do work in correct sequence once the gridview get the focus but its very hard to move focus to the grid itself. Actually focus can be moved to the grid by gridview.Focus(); but this do not move focus to the first element inside the gridview. Therefore when tab is pressed next focus moves outside the gridview altogether.
I'm an asp.net newbie. Basically, I have a DropDownList within and EditItemTemplate within a ListView. When a new item is selected in the drop down, the user would like to NOT have to click the LinkButton for update, but have the update happen automatically. I've experimented with the OnSelectedIndexChanged="ddlrank_itemChanged" using code behind, as well as OnChange="MyFoo()" in javascript, but the details of what to do are beyound me.
I hope I am including the code sample correctly. Any suggestions will be greatly appreciated. Thanks.
<asp:ListView ID="ListView1" runat="server" DataKeyNames="rankingID" DataSourceID="SqlDataSource1" OnItemUpdated="ListView1_Item_Updated">
<LayoutTemplate>
<table cellpadding="2" width="640px" border="1" runat="server" id="tblRankings">
<tr id="Tr1" runat="server">
<th id="Th1" runat="server">Action</th>
<th id="Th3" runat="server">Rank</th>
<th id="Th4" runat="server">Committee name</th>
<th id="Th5" runat="server">Committee type</th>
</tr>
<tr runat="server" id="itemPlaceholder" />
</table>
<asp:DataPager runat="server" ID="RankingDataPager" PageSize="100">
<Fields>
<asp:NextPreviousPagerField ShowFirstPageButton="true" ShowLastPageButton="true"
FirstPageText="|<< " LastPageText=" >>|"
NextPageText=" > " PreviousPageText=" < " />
</Fields>
</asp:DataPager>
</LayoutTemplate>
<ItemTemplate >
<tr id="Tr2" runat="server">
<td>
<asp:LinkButton ID="EditButton" runat="Server" Text="Edit" CommandName="Edit" />
</td>
<td valign="top">
<asp:Label ID="RankLabel" runat="Server" Text='<%#Eval("rank") %>' />
</td>
<td valign="top">
<asp:Label ID="CommitteeNameLabel" runat="Server" Text='<%#Eval("committeename") %>' />
</td>
<td valign="top">
<asp:Label ID="CommitteeTypeLabel" runat="Server" Text='<%#Eval("committeetype") %>' />
</td>
</tr>
</ItemTemplate>
<EditItemTemplate >
<tr style="background-color: #ADD8E6">
<td>
<asp:LinkButton ID="UpdateButton" runat="server" CommandName="Update" Text="Update" />
<asp:LinkButton ID="CancelButton" runat="server" CommandName="Cancel" Text="Cancel" />
</td>
<td>
<asp:DropDownList ID="ddlrank"
DataSourceID="sdsrank"
DataValueField="vchvalue"
DataTextField="vchvalue"
OnSelectedIndexChanged="ddlrank_itemChanged"
OnChange="MyFoo()"
SelectedValue='<%# Bind("rank") %>' runat="server" >
</asp:DropDownList>
</td>
<td>
<asp:TextBox ID="CommitteeNameTextBox" runat="server" Enabled="false" ReadOnly="true" Text='<%#Bind("committeename") %>'
MaxLength="200" /><br />
</td>
<td>
<asp:TextBox ID="CommitteeTypeTextBox" runat="server" Enabled="false" ReadOnly="true" Text='<%#Bind("committeetype") %>'
MaxLength="20" /><br />
</td>
</tr>
</EditItemTemplate>
</asp:ListView>
I think you are missing AutoPostBack="true" on your dropdownlist property. Hope it helps.
You're headed in the right direction. You can use "OnSelectedIndexChanged", or you can create a function in your codebehind page that handles the SelectedIndexChanged event. Either way, when the user makes a selection from the dropdown, you get a postback and that function is executed. In the function you can do whatever you want. In a case like this that might mean checking what the selected value is and setting other values on the screen based on the new selection. When the function exits, a new screen is sent to the user's browser with any updated data.
Thanks for the replies, they helped direct and refine my internet searching!
I finally found a simple solution.
It just requires two lines of code in the OnSelectedIndexChanged code-behind function defined on the dropdownlist:
protected void ddlrank_itemChanged(object sender, EventArgs e)
{
ListViewDataItem item = (ListViewDataItem)((DropDownList)sender).Parent;
ListView1.UpdateItem(item.DisplayIndex, false);
}
Currently i'm working on my final year project.
In a webpage which loads data in gridview, each row has on button which will popup a window and ask for error to write inside **textbox** and submit that error on server.
On the serverside i require two values, first one is the primary key of that row and the error that is written inside **textbox**. It is easy to get primary key value but i'm unable to get value in side the textbox.
I'm attaching the code of .aspx file:
<asp:GridView ID="gvPODetails" runat="server" DataSourceID="Inspection_SqlDataSource"
EnableModelValidation="True" AllowSorting="True" AutoGenerateColumns="False"
BackColor="#CCCCCC" BorderColor="Black" BorderStyle="Solid" BorderWidth="3px" CellPadding="4" ForeColor="Black" CellSpacing="2">
<Columns>
<asp:BoundField DataField="ProductCode" HeaderText="ProductCode" SortExpression="ProductCode" />
<asp:BoundField DataField="MaterialCode" HeaderText="MaterialCode" SortExpression="MaterialCode" />
<asp:TemplateField>
<ItemStyle BorderStyle="None" BorderColor="Transparent" BorderWidth="0px" />
<ItemTemplate>
<asp:LinkButton ID="lnkbtnOk" OnClick="Ok_Click" CommandArgument='<%# Eval("Identity")%>'
runat="server" Text="Ok"></asp:LinkButton>
<asp:LinkButton ID="lnkbtnReject" runat="server" Text="Reject"></asp:LinkButton>
<asp:Panel ID="popUp_Data" runat="server" CssClass="modelPopup" Style="display: none;">
<table style="padding: 10px 10px 10px 10px; width: 100%;">
<tr>
<td>
</td>
<td align="right">
<input id="close_popup" type="image" src="../Images/closebox.gif" />
</td>
</tr>
<tr valign="top">
<td align="right">
<asp:Label ID="lblError" Text="Error" runat="server" CssClass="fontStyle"></asp:Label>
</td>
<td align="left">
<asp:TextBox ID="txtError" runat="server" CssClass="ta"
TextMode="MultiLine"></asp:TextBox>
</td>
</tr>
<tr>
<td>
</td>
<td align="left">
<asp:Button ID="btnSubmit" runat="server" CssClass="sbmt" Text="Reject Item" OnClick="Reject_Click"
CommandArgument='<%# Eval("Identity")%>' />
</td>
</tr>
</table>
</asp:Panel>
<asp:ModalPopupExtender ID="popUp_Data_ModalPopupExtender" runat="server" DynamicServicePath=""
Enabled="True" BackgroundCssClass="modelBackground" PopupControlID="popUp_Data"
TargetControlID="lnkbtnReject" CancelControlID="close_popup">
</asp:ModalPopupExtender>
</ItemTemplate>
</asp:TemplateField>
</Columns>
<EmptyDataTemplate>
<asp:Label runat="server" ID="lblNoDataFound" Text="No Machine Found."></asp:Label>
</EmptyDataTemplate>
</asp:GridView>
What i want is the data inside textbox with id txtError.
Since it is a repeating item, you cannot access it directly using its id. You can use FindControl instead as follows:
var textBoxAux = gridView.Rows[index].FindControl("txtError") as TextBox;
You need to find the index of the row in the event you are handling.
EDIT: finding the index...
Pass the DataItemIndex in the CommandArgument ( instead of the identity ) if applicable.
CommandArgument='<%# Container.DataItemIndex %>'
Ref: ASP.NET GridView RowIndex As CommandArgument
Hey I am trying to recreate the following HTML
<table border="0" cellspacing="0" cellpadding="2" width="100%" id="productListTable">
<tr>
<th rowspan="2">Product Name</th>
<th rowspan="2" >Pack Size</th>
<th rowspan="2" >Trade Price</th>
<th colspan="2" style="border:none;">Discount</th>
<th rowspan="2" >Actual Price</th>
<th rowspan="2">Stock</th>
<th rowspan="2">Quantity</th>
</tr>
<tr class="sub">
<th >PLC</th>
<th >Total</th>
</tr>
In my Gridview the first tr is no problem as this can just be standard header text in my columns but I am wondering how I can add this sub tr
<tr class="sub">
<th >PLC</th>
<th >Total</th>
</tr>
And also how to add this style, to my existing column
<th colspan="2" style="border:none;">Discount</th>
Heres my gridview at the moment
<asp:GridView ID="productListTable" runat="server" DataSourceID="srcProductListPerCustomer" AutoGenerateColumns="False" AlternatingRowStyle-CssClass="tr_dark" HeaderStyle-CssClass="header_req" BorderWidth="0px" GridLines="None" AllowPaging="true" PageSize="25" EmptyDataText="No records." AllowSorting="false" Width="100%" DataKeyNames="product_ID_key" OnRowDataBound="productListTable_RowDataBound" OnRowCommand="productListTable_RowCommand" >
<Columns>
<asp:TemplateField HeaderText="Product Name" HeaderStyle-Width="250px" SortExpression="productName" ItemStyle-CssClass="product_name" >
<ItemTemplate>
<asp:Label ID="ProductNameField" runat="server" Text='<%# Eval("productName").ToString() %>'></asp:Label>
</ItemTemplate>
</asp:TemplateField>
</Columns>
<Columns>
<asp:TemplateField HeaderText="Pack Size" HeaderStyle-Width="70px" SortExpression="packSize">
<ItemTemplate>
<asp:Label ID="PackSizeField" runat="server" Text='<%# Eval("packSize").ToString()%>'></asp:Label>
</ItemTemplate>
</asp:TemplateField>
</Columns>
<Columns>
<asp:TemplateField HeaderText="Trade Price" HeaderStyle-Width="130px" SortExpression="address">
<ItemTemplate>
<asp:Label ID="TradePriceField" runat="server" Text='<%# DisplayMoney(Eval("tradePrice").ToString())%>'></asp:Label>
<asp:Label ID="TradePriceFieldHidden" runat="server" Text='<%# Eval("tradePrice").ToString()%>' Visible="false"></asp:Label>
</ItemTemplate>
</asp:TemplateField>
</Columns>
<Columns>
<asp:TemplateField HeaderText="Discount" HeaderStyle-Width="60px" SortExpression="discount">
<ItemTemplate>
<asp:Label ID="DiscountField" runat="server" Text='<%# Eval("discount").ToString() + "%" %>'></asp:Label>
</ItemTemplate>
</asp:TemplateField>
</Columns>
<Columns>
<asp:TemplateField HeaderText="Actual Price" HeaderStyle-Width="130px" SortExpression="actualPrice">
<ItemTemplate>
<asp:Label ID="ActualPriceField" runat="server" Text='<%# DisplayMoney(Eval("actualPrice").ToString())%>'></asp:Label>
</ItemTemplate>
</asp:TemplateField>
</Columns>
<Columns>
<asp:TemplateField HeaderText="Stock" HeaderStyle-Width="130px" SortExpression="stock_indicator">
<ItemTemplate>
<asp:Label ID="StockField" runat="server" Text='<%# DisplayStockLevel(Eval("stock_indicator").ToString()) %>'></asp:Label>
</ItemTemplate>
</asp:TemplateField>
</Columns>
<Columns>
<asp:TemplateField HeaderText="Quantity">
<ItemTemplate>
<asp:TextBox runat="server" ID="txtQuantity" Columns="5"></asp:TextBox><br />
<asp:LinkButton runat="server" ID="btnRemove" Text="Remove" CommandName="Remove" CommandArgument='<%# Eval("product_ID_key") %>' style="font-size:12px;" Visible="false"></asp:LinkButton>
</ItemTemplate>
</asp:TemplateField>
</Columns>
<HeaderStyle CssClass="header_req" />
<AlternatingRowStyle CssClass="tr_dark" />
<PagerStyle CssClass="pagination" />
<PagerSettings PageButtonCount="3" FirstPageText="First" LastPageText="Last" NextPageText="Next" PreviousPageText="Previous" Mode="NumericFirstLast" />
</asp:GridView>
I'm not sure about your current scenario, but it seems like you might want to take a look at the ListView control.
Out of the box GridView tends to create a ton of extra HTML to get it to look right. I'm not sure you'll ever be able to get exactly what you're looking for that way.
I did see that you have some paging stuff in there; if you go the ListView route, you'll want to use a DataPager as well.
I would use a ListView instead. It's a little more flexible, and you can just spit out table rows through the item template. It won't be the prettiest HTML ever, but if you're looking to use one of the provided ASP.NET controls for the job, that's probably the most forgiving.
I think you can get away with something like this:
<table cellpadding="3" cellspacing="0">
<asp:DataList ID="DataList1" runat="server">
<ItemTemplate>
<tr>
<td>Test</td>
<td>Test again</td>
</tr>
</ItemTemplate>
</asp:DataList>
</table>