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# ADO. Show all posts
Showing posts with label C# ADO. Show all posts

Saturday, August 15, 2009

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:

Use Column Mapping with MappingType.Hidden to Hide Columns in a DataTable

It is possible to use Column mapping with MappingType.Hidden to hide columns in a DataTable of a Dataset before the Fill with the following:

myDS.Tables[0].Columns[i].ColumnMapping = MappingType.Hidden;


Of course, 0 may be substituted with the table name as a string. Unfortunately, this is not very useful if the Fill has already created the DataSet. In that case I would probable just want to use an item template in my data display control (such as a GridView) to output the specific fields. The other option is to run the delete columns on the DataTable, which is simply inefficient. Another losing option is to run a select command on the DataTable, which might have its uses for simply acquiring in memory data as opposed to viewing it.

References: http://www.dotnetspider.com/forum/ViewForum.aspx?ForumId=3888

Tuesday, December 23, 2008

Use a CustomControl to Set UserId and Use as a DataBindable Property

Use a CustomControl (named MembershipUser) to Set UserId and Use as a DataBindable Property. Create a MembershipUser CustomControl that has a property named Value that can be DataBound. For example MembershipUser1.Value would fetch the userId:


[Browsable (true)]
public string Value
{
get
{
MembershipUser currentUser;
currentUser = Membership.GetUser();
if (currentUser == null)
return string.Empty;
return currentUser.ProviderUserKey.ToString();
}
}
Reference: This is from http://aspnet.4guysfromrolla.com/articles/110106-1.aspx

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

Thursday, October 25, 2007

Adding a Checkbox Column to a GridView and checking if it is checked.

In my project I bind a DataTable to a Gridview. I have two fields in my DataTable: (bool) isChecked and (string) Value. Below I bind the data to those fields in the first two columns. The last Column I used a TemplateField and ItemTemplate to create a CheckBox row that is editable.



<asp:GridView ID="GridView1" runat="server"
OnDataBound="GridView1_DataBound"
OnSelectedIndexChanged="GridView1_SelectedIndexChanged"
AutoGenerateColumns="False" >
<Columns>
<asp:CheckBoxField DataField="isChecked" HeaderText="Select" />
<asp:BoundField DataField="Value" HeaderText="Value" />
<asp:TemplateField HeaderText="Custom Select">
<ItemTemplate>
<asp:CheckBox ID="chkSelect" runat="server" />
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>


Once the user edits the Custom Select checkboxes and pushes the button (btnSumbit), I read which fields are checked. If checked, I read from a Hashtable the value associated with the key.


protected void btnSubmit_Click(object sender, EventArgs e)
{
string sQueryString = "http://foo?";
// load hashtable with key values
Hashtable vhtTags = (Hashtable)Cache["htTags"];
bool isChecked;
// parse through to see what values are selected in gridview
foreach (GridViewRow vRow in GridView1.Rows)
{
isChecked = ((CheckBox)vRow.FindControl("chkSelect")).Checked;
if (isChecked)
{
string skey = vRow.Cells[1].Text.Trim();
sQueryString += vhtTags[skey].ToString();
}
}
lblResult.Text = sQueryString;
}
}

Notes: Since the first check column is only for demonstration and the last column is not bound because the default values are false. For the sake of brevity, error checking is left out.
Reference: link

Wednesday, October 24, 2007

Reversing the Keys and Values in a Hashtable

Here's how to reverse the Keys and Values in a Hashtable. I use the results and overwrite the original ht.Adds.
The results are output into the TextBox txtReversed.Text


protected void btnReverseHash_Click(object sender, EventArgs e)
{
Hashtable ht = new Hashtable();
ht.Add("a1", "Ask");
ht.Add("a2", "Ask what your country can do for you");
ht.Add("a3", "Ask what you can do for your country");
IDictionaryEnumerator _enum = ht.GetEnumerator();
string sOut = "";
const string _FRONT = "ht.Add(";
const string _END = ");\n";
const string _Q = "\"";
const string _CS = ", ";
while (_enum.MoveNext())
{
sOut += _FRONT + _Q + _enum.Value.ToString() + _Q + _CS
+ _Q + _enum.Key.ToString() + _Q + _END;
}
txtReversed.Text = sOut;
}

Wednesday, October 17, 2007

Sorting a GridView that is detached from database and put in a cache

First, the GridView needs to have sorting enabled and a sorting method:


<asp:GridView ID="GridView2" runat="server"
OnSorting="GridView2_Sorting" AllowSorting="True">
</asp:GridView>

Next, the page load and sorting method need to be implemented. I loaded my data from another GridView at the load. There is a Label that is also used. This code is similar to this reference link.


protected void Page_Load(object sender, EventArgs e)
{
DataView myDataView;

// Retrieve the DataView object from Cache. If not exist, then add DataView object to the Cache.

myDataView = (DataView)Cache["MyDataSet"];

if (myDataView == null)
{
myDataView = getTable().DefaultView;
Cache["MyDataSet"] = myDataView;
myDataView.Sort = myDataView.Table.Columns[0].ToString() + " ASC";
lblCacheMsg.Text = "Dataset created explicitly";
}
else
{
lblCacheMsg.Text = "Dataset retrieved from cache";
}
GridView2.DataSource = myDataView;
GridView2.DataBind();
}

// Verbose sort version
protected void GridView2_Sorting(object sender, GridViewSortEventArgs e)
{
DataView Source = (DataView)Cache["MyDataSet"];
string direction = " DESC";
string curDirecton = Source.Sort.ToString().ToUpper();
if (curDirecton.Contains(direction))
{
direction = ASC;
}
else
{
direction = DESC;
}
Source.Sort = e.SortExpression + " " + direction;
Cache["MyDataSet"] = Source;
GridView2.DataSource = Source;
GridView2.DataBind();
lblE.Text = direction;
}
private DataTable getTable()
{
DataTable retVal;
DataTableHelper dth = new DataTableHelper(GridView1);
retVal = dth.getDataTable();
return retVal;
}

Saturday, October 6, 2007

Swapping GridView DataSourceID from DataSource

Here's the simple code for swapping the GridView back to DataSourceID from DataSource:


protected void DropDownListListsInUser_SelectedIndexChanged(object sender, EventArgs e)
{
GridViewStocksInList.DataSource = null;
GridViewStocksInList.DataSourceID = SqlDataSourceGetStocksInList.ID;
GridViewStocksInList.DataBind();
}

The solution came from here.
It suggested studying this.

Thursday, October 4, 2007

Using a GridView to make calculations and avoid Database changes by merging DataTables and using PrimaryKey.

Merging DataTables named dt and dt2.

Before I show the diffences, here are the contents of dt (Figure 1) and dt2 (Figure 2):

Symbol Name Exchange
FRE Freddie Mac NYSE
FRE/PB Freddie Mac NYSE
FRE/PF Freddie Mac NYSE
FRE/PG Freddie Mac NYSE
FRE/PH Freddie Mac NYSE
Figure 1. dt

Symbol EPS Growth Lower Price Target Lower % Target Upper Price Target Upper % Target
FRE FRE FRE FRE FRE FRE
FRE/PB FRE/PB FRE/PB FRE/PB FRE/PB FRE/PB
FRE/PF FRE/PF FRE/PF FRE/PF FRE/PF FRE/PF
FRE/PG FRE/PG FRE/PG FRE/PG FRE/PG FRE/PG
FRE/PH FRE/PH FRE/PH FRE/PH FRE/PH FRE/PH
Figure 2. dt2

In my project I want to use a GridView and append calculated data without changing the database.
My solution is to read the GridView into a DataTable, dt. Then, I make calculations from a PrimaryKey of dt and use the same PrimaryKey for dt2 while adding actual calculations (EPS Growth, Lower Price Target, ... in production version). The final step is to Merge the datatables with dt.Merge(dt2). The result is shown in Figure 3.

Symbol Name Exchange EPS Growth Lower Price Target Lower % Target Upper Price Target Upper % Target
FRE Freddie Mac NYSE FRE FRE FRE FRE FRE
FRE/PB Freddie Mac NYSE FRE/PB FRE/PB FRE/PB FRE/PB FRE/PB
FRE/PF Freddie Mac NYSE FRE/PF FRE/PF FRE/PF FRE/PF FRE/PF
FRE/PG Freddie Mac NYSE FRE/PG FRE/PG FRE/PG FRE/PG FRE/PG
FRE/PH Freddie Mac NYSE FRE/PH FRE/PH FRE/PH FRE/PH FRE/PH
Figure 3.

If you simply Merge with dt.Merge(dt2), you would get the same result as long as the PrimaryKey is set in dt. However, without setting the PrimaryKey you get the result in Figure 4.

Symbol Name Exchange EPS Growth Lower Price Target Lower % Target Upper Price Target Upper % Target
FRE Freddie Mac NYSE
FRE/PB Freddie Mac NYSE
FRE/PF Freddie Mac NYSE
FRE/PG Freddie Mac NYSE
FRE/PH Freddie Mac NYSE
FRE FRE FRE FRE FRE FRE
FRE/PB FRE/PB FRE/PB FRE/PB FRE/PB FRE/PB
FRE/PF FRE/PF FRE/PF FRE/PF FRE/PF FRE/PF
FRE/PG FRE/PG FRE/PG FRE/PG FRE/PG FRE/PG
FRE/PH FRE/PH FRE/PH FRE/PH FRE/PH FRE/PH
Figure 4.

In my implementation I use:
dt.Merge(dt2, false, MissingSchemaAction.Ignore);
This will avoid preserving changes and ignore taking action when there is a missing schema.

Wednesday, October 3, 2007

Loading a GridView into a DataTable and then back to another GridView

First, Loading a GridView into a DataTable, dt:


private void initDataTable()
{

int i = 0;
int j = 0;
int totRow = GridView1.Rows.Count;
int totCol = GridView1.Rows[0].Cells.Count;
// Set the table headers
string[] arrHeaders = {"Symbol","Name","Exchange" };
// Get the table headers
for (j = 0; j < totCol; j++)
{
// The commented line would work if the Gridview had Column HeaderText
//dt.Columns.Add(new DataColumn(GridView1.Columns[col].HeaderText, typeof(string)));

// Instead I use the Headers array, arrHeaders
dt.Columns.Add(new DataColumn(arrHeaders[j].ToString(), typeof(string)));
}
DataRow dr;
for (i = 0; i < totRow; i++)
{
dr = this.dt.NewRow();
for (j = 0; j < totCol; j++)
{
dr[j] = GridView1.Rows[i].Cells[j].Text;
}
this.dt.Rows.Add(dr);
}
}

Then back to another GridView:


private void fillGridView2()
{
if (dt.Rows.Count > 0)
{
GridView2.DataSource = dt;
GridView2.DataBind();
}
else
{
dt.Rows.Add(dt.NewRow());
GridView2.DataSource = dt;
GridView2.DataBind();

int TotalColumns = GridView2.Rows[0].Cells.Count;
GridView2.Rows[0].Cells.Clear();
GridView2.Rows[0].Cells.Add(new TableCell());
GridView2.Rows[0].Cells[0].ColumnSpan = TotalColumns;
GridView2.Rows[0].Cells[0].Text = "No Record Found";
}
}

The no record found code was from this link.

Monday, September 17, 2007

GridView table headers and iterating over a GridView cells in the row and columns.

Here is a function to get the GridView's table header columns:


protected string getTableHeaders()
{
string retVal = "";
int TotalColumns = GridView1.Columns.Count;
int col = 0;
for (col = 0; col < TotalColumns; col++)
{
retVal += GridView1.Columns[col].HeaderText;
if ((col + 1) < TotalColumns) retVal += ", ";
}
return retVal;
}


Here is how to iterate over the GridView cells to extract row and column data into a string. The cells can be custom delimited. Notice how this does not include Column.HeaderText :


protected string getDataCells()
{
string retVal = "";
int TotalColumns = GridView1.Columns.Count;
int TotalRows = GridView1.Rows.Count;
int col = 0;
int row = 0;
if (TotalColumns > 0 && TotalRows > 0)
{
for (row =0; row<TotalRows; row++)
{
for (col = 0; col < TotalColumns; col++)
{ // uses arbitrary ',' between column cells
retVal += GridView1.Rows[row].Cells[col].Text;
if ((col + 1) < TotalColumns) retVal += ", ";
}
// uses arbitrary ';' for end of row
retVal += ";";
}
}
return retVal;
}

Sunday, September 16, 2007

DataGridView cell contents and header contents




// How do I get the contents of a GridView cell?
GridView1.Rows[0].Cells[0].Text;
// Note: This will only get the result data and not the table headers a.k.a. column names.

// How do I get the contents of a GridView table header (<th>) a.k.a. column name?
GridView1.Columns[0].HeaderText;

Friday, September 14, 2007

Nested GridView with subtotals, totals, and counts

This complicated example shows a nested GridView with subtotals, totals, and counts. The actual process of modifying the GridView ItemTemplates is not explained here. Note: The SQL should be replaced with a stored procedure for production.
NestedGridView example


<script runat="server">
Decimal masterTotal = 0;
Decimal masterCount = 0;
Decimal priceTotal = 0;
int priceCount = 0;
protected void GridView1_RowDataBound(object sender, GridViewRowEventArgs e)
{

if (e.Row.RowType == DataControlRowType.DataRow)
{
SqlDataSource s = (SqlDataSource)e.Row.FindControl("SqlDataSource2");
String str = e.Row.Cells[0].Text;
s.SelectParameters[0].DefaultValue = e.Row.Cells[0].Text;

}
}

protected void GridView2_RowDataBound(object sender, GridViewRowEventArgs e)
{

if (e.Row.RowType == DataControlRowType.DataRow)
{
// add the UnitPrice and QuantityTotal to the running total variables
priceTotal += Convert.ToDecimal(DataBinder.Eval(e.Row.DataItem, "contribution_amount"));
priceCount++;
masterCount++;
}
else if ((e.Row.RowType == DataControlRowType.Footer) )
{
masterTotal += priceTotal;
if (priceCount > 1)
{
e.Row.Cells[0].Text = "Subtotal:";
// for the Footer, display the running totals
e.Row.Cells[2].Text = priceCount.ToString();
e.Row.Cells[3].Text = priceTotal.ToString("c");
e.Row.Cells[3].HorizontalAlign = e.Row.Cells[2].HorizontalAlign = HorizontalAlign.Right;
e.Row.Font.Bold = true;
{
GridView1.FooterRow.Cells[0].Text = "Total:";
// for the Footer, display the running totals
GridView1.FooterRow.Cells[1].Text = masterCount.ToString();
GridView1.FooterRow.Cells[1].Text += "&nbsp&nbsp&nbsp&nbsp" + masterTotal.ToString("c");
GridView1.FooterRow.Cells[1].HorizontalAlign = GridView1.FooterRow.Cells[1].HorizontalAlign = HorizontalAlign.Right;
GridView1.FooterRow.Font.Bold = true;
}
}
else if (priceCount == 1)
{// blank out borders and background color for 1 row footers

e.Row.Visible = false;
}
else
{
e.Row.Visible = false;
}
priceTotal = 0;
priceCount = 0;
}
}


</script>

Here is the html part of the aspx:


<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
<title>Campaign Finance Contributions By Date</title>
</head>
<body>
<form id="form1" runat="server">
<div>
<table align="center">
<tr>
<td align="center" nowrap="nowrap" style="width: 253px; height: 92px">
<asp:Image ID="TelWebImage" runat="server" ImageAlign="Middle" ImageUrl="~/tel-web.gif"
Style="z-index: 101; left: 7px; position: relative; top: 9px" /></td>
</tr>
<tr>
<td align="center" nowrap="nowrap" style="width: 253px; height: 42px">
<asp:Label ID="TitleLabel" runat="server" Font-Size="Larger" Style="z-index: 100;
left: 4px; position: relative; top: 0px"
Text="Campaign Finance Contributions"
Width="206px"></asp:Label></td>
</tr>
<tr>
<td align="center" nowrap="nowrap" style="width: 253px">
<asp:Label ID="ByDateLabel" runat="server" Style="z-index: 102; left: 16px; position: relative;
top: 0px"
Text="BY CONTRIBUTION DATE"></asp:Label></td>
</tr>
<tr>
<td align="center" nowrap="nowrap" style="width: 253px; height: 19px">
<asp:Label ID="DateTimeLab" runat="server" Style="left: 0px; position: relative;
top: 2px"
Text="Date and Time"></asp:Label></td>
</tr>
</table>
</div>
&nbsp;&nbsp;
<asp:SqlDataSource ID="SqlDataSource1" runat="server" ConnectionString="<%$ ConnectionStrings:ConnectionString %>"
SelectCommand="SELECT DISTINCT contribution_date FROM ContributionCandidateview WHERE (contribution_number LIKE @contribution_number)">
<SelectParameters>
<asp:Parameter DefaultValue="%" Name="contribution_number" />
</SelectParameters>
</asp:SqlDataSource>
<asp:ObjectDataSource ID="ObjectDataSource1" runat="server"></asp:ObjectDataSource>
<asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="False" DataSourceID="SqlDataSource1" OnRowDataBound="GridView1_RowDataBound" ShowFooter="True">
<Columns>
<asp:BoundField DataField="contribution_date" HeaderText="contribution_date" SortExpression="contribution_date" />
<asp:TemplateField HeaderText="Contributions">
<ItemTemplate>
&nbsp;
<asp:SqlDataSource ID="SqlDataSource2" runat="server" ConnectionString="<%$ ConnectionStrings:ConnectionString %>"
SelectCommand="SELECT [candidate_name], [contribution_date], [contribution_name1], [contribution_amount] FROM [ContributionCandidateview] WHERE ([contribution_date] = @contribution_date)">
<SelectParameters>
<asp:Parameter Name="contribution_date" Type="DateTime" />
</SelectParameters>
</asp:SqlDataSource>
<asp:GridView ID="GridView2" runat="server" DataSourceID="SqlDataSource2" OnRowDataBound="GridView2_RowDataBound" ShowFooter="True" Width="500px">
<AlternatingRowStyle BorderColor="White" BackColor="#E0E0E0" />
<FooterStyle BackColor="#DFFFDF" />
<HeaderStyle BackColor="#DFDFFF" />
</asp:GridView>
</ItemTemplate>
<ItemStyle VerticalAlign="Bottom" />
</asp:TemplateField>
</Columns>
<FooterStyle BackColor="#DFDFFF" />
</asp:GridView>
</form>
</body>
</html>

Modifying the contents of a GridView after DataBinding

This is more than bare functionality, but it can be simplified by eliminating the contents in foreach brackets.


protected void GridView1_DataBound(object sender, EventArgs e)
{
foreach (GridViewRow dgrow in GridView1.Rows)
{
String myString, myPattern;
Boolean result;
myPattern = txtSearch.Text;
myString = dgrow.Cells[0].Text;
result = true;

if (isEndsWith == true)
{
if (myPattern.Length > 0)
{
result = myString.EndsWith(myPattern);
dgrow.Cells[0].Text = myString.Substring(0, myString.LastIndexOf(myPattern))
+ HighlightText(myPattern, myString.Substring(myString.LastIndexOf(myPattern)));
}
else result = false;
if (result == false)
dgrow.Cells[0].Visible = false;
}
else
{
if (isStartsWith)
{
if (myPattern.Length > 0)
{
result = myString.StartsWith(myPattern);
dgrow.Cells[0].Text = HighlightText(myPattern, myString.Substring(0,myPattern.Length)) + myString.Substring(myPattern.Length, myString.Length-myPattern.Length);
dgrow.Cells[0].Visible = true;
}
}
else
{
dgrow.Cells[0].Text = HighlightText(myPattern, myString);
dgrow.Cells[0].Visible = true;
}
}
}
}