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.

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;
}

Monday, October 8, 2007

Modifying display of your GridView with CSS

If you manage multiple GridViews that you want to have the same format, use CSS classes. In the Styles section of the GridView properties there are:
  • AlternatingRowStyle
  • EditRowStyle
  • EmptyDataRowStyle
  • FooterStyle
  • HeaderStyle
  • PagerStyle
  • RowStyle
  • SelectedRowStyle
In this example I'll create classes in my CSS file as such:


.tableAnalysisRow {
border-right:#000 thin solid;
border-bottom:#000 thin solid;
background:#fff;
color:#000;
border-top:#000 thin solid;
border-left:#000 thin solid;
padding:2px 2px 3px 4px;
}
.tableAnalysisAlternatingRow {
border-right:#000 thin solid;
border-bottom:#000 thin solid;
background:#DCDCDC;
color:#000;
border-top:#000 thin solid;
border-left:#000 thin solid;
padding:2px 2px 3px 4px;
}
.tableAnalysisHeader {
border-right:#000 thick solid;
border-bottom:#000 thick solid;
background:#DCDCDC;
color:#000;
border-top:#000 thick solid;
border-left:#000 thick solid;
font-weight:700;
border-collapse:separate;
border-color:#000;
padding: 2px 2px 3px 4px;
}

Now just modify the Class property in the appropriate Gridview Style property like the following:


<asp:GridView ID="GridView1" runat="server" >
<RowStyle CssClass="tableAnalysisRow" />
<HeaderStyle CssClass="tableAnalysisHeader" />
<AlternatingRowStyle CssClass="tableAnalysisAlternatingRow" />
</asp:GridView>

The result GridView is here.

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.

Friday, October 5, 2007

Help user redirect to secure target page after login and avoid extra navigation

Here's a solution for when the user needs to log in before accessing a secure page. This allows the user to avoid going through the menu system to go to the original page desired. I avoid some kind of error by using the false parameter in the redirect. The querystring of note is ReturnUrl.


protected void Page_Load(object sender, EventArgs e)
{
if (User.Identity.IsAuthenticated == false)
{
Response.Redirect("Login.aspx?ReturnUrl=DesiredPage.aspx", false);
}
else
{
MembershipUser user = Membership.GetUser().ProviderUserKey.ToString();
}
}

RedirectFromLoginPage Method

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.