Programming Journal C#, Java, SQL and to a lesser extent HTML, CSS, XML, and regex. I made this so other programmers could benefit from my experience.

Showing posts with label C# GridView. Show all posts
Showing posts with label C# GridView. Show all posts

Saturday, August 15, 2009

Highlight Rows in a GridView

To highlight rows in a GridView you will want to use the GridView DataBound event to add the onmouseover and onmouseout attributes. While CSS methods may work in FireFox browsers, they do not work in Internet Explorer. For the associated javascript method, you can directly set it with this.style.backgroundColor, but this is inflexible. Instead, change the CSS class.

Here is the CSS for the highlighted and normal row (see reference for source of the simple CSS):

<style type="text/css">

.normalRow
{
background-color:white;/* You can update the background Color to normal Gridview Back Color */
cursor:pointer;/* You can change cursor pointer to default, Pointer etc */
}

.highlightRow
{
background-color:Gray;/* You can change the background Color of the row to whatever color you want. You can also give Hexadecimal color code also */
cursor:pointer;/* You can change cursor pointer to default, Pointer etc */
}

</style>


Here is the CodeBehind for the GridView DataBound event:

protected void GridView1_DataBound(object sender, EventArgs e)
{
foreach (GridViewRow row in GridView1.Rows)
{
if (row.RowType == DataControlRowType.DataRow)
{
row.Attributes.Add("onmouseout", "this.className='normalRow'");
row.Attributes.Add("onmouseover", "this.className='highlightRow'");
}
}
}


Further modifications for multiple class rows can be made by checking the original CssClass (or checking implicitly by rowCount%currentRow for alternating rows) in the CodeBehind and setting the onmouseout event to switch back to that original class. Another example where this may be necessary is with check box rows that can be selected.


References:

Rid Grid Lines or Borders in a GridView

Here is how to get rid of Grid lines or borders in a GridView:


<asp:GridView ID="GridView1" GridLines=None runat="server">
</asp:GridView>


References: http://forums.asp.net/t/1134618.aspx

Creating a Pageable Gridview with Customized Pager Buttons


Matt Berseth put together a great post on creating a pageable GridView. It is basically a custom control that inherits from GridView and implements the DataPageable interface. The coolest part is how the GridView CSS is tailored to a specific looking type of Gridview.

I think it is worth going one step further and tailoring the DataPager with custom images to indicate both enabled and disabled. You will notice that there is a FirstPageImageUrl in the NextPreviousPagerField but no available FirstPage_DisabledImageUrl. To overcome this, we need to examine the DataPager controls dynamically and switch the images according to whether we are already at the start index or last index. This code is placed in the GridView's DataBound event:

protected void gvProducts_DataBound(object sender, EventArgs e)
{
ImageButton ibtn;
int pgEnd = gvProducts.PageCount;
int curPg = gvProducts.PageIndex;
foreach (Control ct in pager.Controls[0].Controls)
{
if(ct.GetType().Equals(typeof(ImageButton)))
{
ibtn = ct as ImageButton;
if (0 == curPg)
{
ibtn.ImageUrl = "~/images/PageFirst_Disabled.jpg";
}
else { ibtn.ImageUrl = "~/images/PageFirst.jpg"; }
}
}
foreach (Control ct in pager.Controls[2].Controls)
{
if (ct.GetType().Equals(typeof(ImageButton)))
{
ibtn = ct as ImageButton;
if ((pgEnd-1) == curPg)
{
ibtn.ImageUrl = "~/images/PageLast_Disabled.jpg";
}
else { ibtn.ImageUrl = "~/images/PageLast.jpg"; }
}
}
}


I also changed the section in Matt's Default.aspx to:


<!-- Notice this is outside the GridView -->
<div class="pager">
<asp:DataPager ID="pager" runat="server" PageSize="8" PagedControlID="gvProducts">
<Fields>
<asp:NextPreviousPagerField
ButtonType="Image"
FirstPageImageUrl="~/images/PageFirst.jpg"
RenderDisabledButtonsAsLabels="false"
ShowFirstPageButton="true" ShowPreviousPageButton="false"
ShowLastPageButton="false" ShowNextPageButton="false"
/>
<asp:NumericPagerField
ButtonCount="7" NumericButtonCssClass="command"
CurrentPageLabelCssClass="current" NextPreviousButtonCssClass="command"
/>
<asp:NextPreviousPagerField

ButtonType="Image"
LastPageImageUrl="~/images/PageLast.jpg"
RenderDisabledButtonsAsLabels="false"
ShowFirstPageButton="false" ShowPreviousPageButton="false"
ShowLastPageButton="true" ShowNextPageButton="false"
/>
</Fields>
</asp:DataPager>
</div>


The crude Microsoft Paint images are located here: http://techron.scottrichmond.com/downloads/2210036646138181629images.zip

Now you know a technique to customize the DataPager. I further customized the buttons to display custom buttons (print, search, etc.) in the center and pager buttons on the right using JavaScript. That involves a lot of screen calculation details and JavaScript that is another topic. Note, the customization comes at a performance cost. This can be improved with direct reference to the control[x].FindControl("myImgControl"), but that requires inspecting how .NET names the ImageButton in the Debugger.

The result is customized ImageButtons for enabled and disabled buttons.

Download/view Matt's code to add in the customization I've written about.

References:

Tuesday, December 23, 2008

Modifying DataBound Hyperlinks Text

Modifying a GridView's Databound Hyperlink text since I couldn't do this easily in the ItemTemplate, I moved the Replace function to the DataBound of the GridView:


protected void GridViewStocksInLists_DataBound(object sender, EventArgs e)
{
int rowId;
string imgUrl;
string navUrl;
for (rowId=0; rowId<GridViewStocksInLists.Rows.Count;rowId++) {
imgUrl = string.Empty;
navUrl = string.Empty;
imgUrl = ((HyperLink)GridViewStocksInLists.Rows[rowId].FindControl("hlChart")).ImageUrl.Replace('$', '^');
((HyperLink)GridViewStocksInLists.Rows[rowId].FindControl("hlChart")).ImageUrl = imgUrl;
navUrl = ((HyperLink)GridViewStocksInLists.Rows[rowId].FindControl("hlChart")).NavigateUrl.Replace('$', '^');
((HyperLink)GridViewStocksInLists.Rows[rowId].FindControl("hlChart")).NavigateUrl = navUrl;
}
}
This replaced $ with ^ in my HyperLink.

Here is the GridView that contains the HyperLink:

<asp:GridView ID="GridViewStocksInLists" runat="server" DataSourceID="SqlDataSourceGetStocksInList">
<RowStyle CssClass="tableAnalysisRow" />
<HeaderStyle CssClass="tableAnalysisHeader" />
<AlternatingRowStyle CssClass="tableAnalysisAlternatingRow" />
<Columns>
<asp:TemplateField HeaderText="Chart">
<ItemTemplate>
<asp:HyperLink ID="hlChart" runat="server"
ImageUrl='<%# Eval("Symbol", "http://chart.finance.yahoo.com/c/0b/d/{0}").ToLower() %>'
NavigateUrl='<%# Eval("Symbol", "http://finance.yahoo.com/q/bc?s={0}&t=1y").ToLower() %>' >
</asp:HyperLink>
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>

References: http://forums.asp.net/p/1263726/2542303.aspx#2542303

Tuesday, December 16, 2008

Sorting a GridView

Sorting a GridView with a DataSource requires an external storage variable for a the last SortDirection. First, I call the GridViewReport_Sorting in the Sorting event in the GridView. A GridView has e.SortExpression and e.SortDirection. I combine the two to form a unique Session variable and then set the SortDirection to compare at later sorts:

protected void GridViewReport_Sorting(object sender, GridViewSortEventArgs e)
{
DataTable dt;
DataView dv;
dt = (DataTable)Cache["dvStocks"];
dv = new DataView(dt);
string direction = SortDirection.Descending.ToString();
string curDirecton = SortDirection.Ascending.ToString(); // set to default
string key = string.Concat(e.SortExpression, e.SortDirection);
if(Session[key]!=null) {
curDirecton = (string)Session[key];
}
if (curDirecton.Contains("Ascending"))
{
direction = Global.DESC; //DESC
Session[key] = SortDirection.Descending.ToString();
}
else
{
direction = Global.ASC; //ASC
Session[key] = SortDirection.Ascending.ToString();
}
dv.Sort = e.SortExpression + " " + direction;
Cache["dtCalculated"] = dv.ToTable();
GridViewReport.DataSource = dv;
GridViewReport.DataBind();
}

Reference: http://forums.asp.net/t/825118.aspx

Thursday, July 3, 2008

Using a GridView with Edit and Delete that use stored procedures

Here is how to use a GridView with Edit and Delete that use stored procedures for update and delete. First, the aspx:

<asp:GridView ID="gvEmail" runat="server" AutoGenerateDeleteButton="True"
AutoGenerateEditButton="True" AutoGenerateColumns="False" DataSourceID="SqlDataSource1"
AllowPaging="True" OnRowDeleting="gvEmail_RowDeleting" PageSize="99" OnRowUpdating="gvEmail_OnRowUpdating">
<Columns>
<asp:BoundField DataField="email" HeaderText="email" SortExpression="email" />
</Columns>
</asp:GridView>
<asp:SqlDataSource ID="SqlDataSource1" runat="server" ConnectionString="<%$ ConnectionStrings:ConnectionString %>"
SelectCommand="SELECT [email] FROM [vw_Email]"
DeleteCommand="sproc_DeleteEmail" DeleteCommandType="StoredProcedure"
UpdateCommand="sproc_UpdateEmail" UpdateCommandType="StoredProcedure"
>
<DeleteParameters><asp:Parameter Name="email" Type="String" /></DeleteParameters>
<UpdateParameters>
<asp:Parameter Name="email" Type="String" />
<asp:Parameter Name="newEmail" Type="String" />
</UpdateParameters>
</asp:SqlDataSource>
Now the code behind.

protected void gvEmail_RowDeleting(object sender, GridViewDeleteEventArgs e) //DELETE
{
SqlConnection conn = new SqlConnection(SqlDataSource1.ConnectionString);
System.Data.SqlClient.SqlCommand command = new System.Data.SqlClient.SqlCommand("sproc_DeleteEmail", conn);
command.CommandType = System.Data.CommandType.StoredProcedure;
conn.Open();
string email = string.Empty;
DataControlFieldCell cell = gvEmail.Rows[e.RowIndex].Cells[1] as DataControlFieldCell;
gvEmail.Columns[0].ExtractValuesFromCell(
e.Keys,
cell,
DataControlRowState.Normal,
true);
email = e.Keys[0].ToString();
if (!string.IsNullOrEmpty(email))
{
command.Parameters.AddWithValue("@email", email);
command.ExecuteNonQuery();
}
command.Parameters.Clear();
conn.Close();
}
protected void gvEmail_OnRowUpdating(object sender, GridViewUpdateEventArgs e)
{
SqlConnection conn = new SqlConnection(SqlDataSource1.ConnectionString);
System.Data.SqlClient.SqlCommand command = new System.Data.SqlClient.SqlCommand("sproc_UpdateEmail", conn);
command.CommandType = System.Data.CommandType.StoredProcedure;
conn.Open();
string newEmail = e.NewValues[0] as string;
string email = e.OldValues[0] as string;
if (!string.IsNullOrEmpty(email))
{
command.Parameters.AddWithValue("@email", email);
command.Parameters.AddWithValue("@newEmail", newEmail);
command.ExecuteNonQuery();
}
command.Parameters.Clear();
conn.Close();
}
Note: Exception handling left off for brevity.
Reference: http://www.developerfusion.co.uk/show/91/7/

Tuesday, July 1, 2008

Using XML and XPath for a GridView

This demonstrates how to use XML and XPath with a GridView to display links:

<asp:GridView ID="gvLinks" runat="server" DataSourceID="XmlDataSource1" AutoGenerateColumns="False">
<Columns>
<asp:TemplateField HeaderText="Link">
<ItemTemplate>
<asp:HyperLink ID="HyperLink1" runat="server" Target="_blank" NavigateUrl='<%#XPath("href") %>'>
<%#XPath("title")%>
</asp:HyperLink>
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="Description">
<ItemTemplate>
<asp:Label ID="lblrOwner" runat="server" Text=&lt;%#XPath("description")%&gt;></asp:Label>
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
<asp:XmlDataSource ID="XmlDataSource1" runat="server" DataFile="~/App_Data/Links.xml"
XPath="links/link"></asp:XmlDataSource>
Here is the XML file:

<?xml version="1.0" encoding="utf-8" ?>
<links>
<link>
<title>Yahoo</title>
<href>http://www.yahoo.com/</href>
<owner>Yang</owner>
<description>Yahoo web portal</description>
</link>
<link>
<title>MSN</title>
<href>http://www.msn.com/</href>
<owner>Balmer</owner>
<description>Microsoft web portal</description>
</link>
<link>
<title>Delicious</title>
<href>http://del.icio.us/</href>
<owner></owner>
<description>Internet bookmark manager</description>
</link>
<link>
<title>YouTube</title>
<href>http://youtube.com/</href>
<owner></owner>
<description>Internet videos</description>
</link>
<link>
<title>SlashDot</title>
<href>http://slashdot.org/</href>
<owner></owner>
<description>News that matters</description>
</link>

</links>
Reference: http://bytes.com/forum/thread528704.html

Thursday, June 5, 2008

Clearing controls in GridView row using delete

Here is how to clear controls in GridView row using delete. Be careful that GridViewDeleteEventArgs is not GridViewDeletedEventArgs!

<asp:GridView ID="gvStolenStatusInfo" runat="server" AutoGenerateColumns="false" AllowPaging="true"
EmptyDataText="No records found." PageSize="10" CssClass="gridView"
OnRowDeleting="gvStolenStatusInfo_RowDeleting" AutoGenerateDeleteButton="true">
<Columns>
<asp:TemplateField HeaderText="Status">
<ItemTemplate>
<asp:TextBox ID="txtuCode" runat="server" Text='<%# Bind("Code") %>' />
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="Comment">
<ItemTemplate>
<asp:TextBox ID="txtuComment" runat="server" Text='<%# Bind("Comment") %>' />
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
Notice the OnRowDeleting set to x_RowDeleting function and AutoGenerateDeleteButton. Now for the delete function:

protected void gvStolenStatusInfo_RowDeleting(object sender, GridViewDeleteEventArgs e)
{
int rowID = e.RowIndex;
((TextBox)gvStolenStatusInfo.Rows[rowID].FindControl("txtuCode")).Text = string.Empty;
((TextBox)gvStolenStatusInfo.Rows[rowID].FindControl("txtuDate")).Text = string.Empty;
}
References: http://www.codeproject.com/KB/webforms/Editable_GridView.aspx

Monday, May 5, 2008

Multiple PostBack problem with GridView

I noticed my SelectedIndexChanged method being called twice in IE7 when I selected a gridview row. I used solution 2 at http://www.codeproject.com/KB/aspnet/GVImageCommandButtonProb.aspx to solve the problem.