Tuesday, December 7, 2010

Maintaining CheckBox State of multiple GridViews

0 comments
Almost two years back, I did a post on Maintaining State of Checkbox while Paging in Gridview

This post is an extension to it. this is the code to maintain CheckBox states of multiple gridviews in a page.

The logic is simple. We are storing the primary keys of the checkboxes that are checked into a List<T> where T = data type of the primary key. This is done at PageIndexChanging before we change the page index and re-bind the GridView. And at RowDataBound we are checking whether the DataKeyName(primary key) of each row is in the List. If present , we mark the CheckBox as checked.

At ASPX

<asp:GridView ID="gvProducts" runat="server" 
            AllowPaging="True" 
            AutoGenerateColumns="False"
            DataKeyNames="ProductID"
            OnPageIndexChanging="gvProducts_PageIndexChanging" 
            OnRowDataBound="gvProducts_RowDataBound">
    <Columns>
        <asp:TemplateField HeaderText="Select">
            <ItemTemplate>
                <asp:CheckBox ID="chkSelect" runat="server" />
            </ItemTemplate>
        </asp:TemplateField>
        <asp:BoundField DataField="ProductID" HeaderText="ProductID" InsertVisible="False"
        ReadOnly="True" SortExpression="ProductID" />
        <asp:BoundField DataField="ProductName" HeaderText="ProductName" SortExpression="ProductName" />
    </Columns>
</asp:GridView>
<asp:GridView ID="gvCustomers" runat="server" 
            AllowPaging="True" 
            AutoGenerateColumns="False"
            DataKeyNames="CustomerID"
            OnPageIndexChanging="gvCustomers_PageIndexChanging" 
            OnRowDataBound="gvCustomers_RowDataBound">
    <Columns>
        <asp:TemplateField HeaderText="Select">
            <ItemTemplate>
                <asp:CheckBox ID="chkSelect" runat="server" />
            </ItemTemplate>
        </asp:TemplateField>
        <asp:BoundField DataField="CustomerID" HeaderText="ID" InsertVisible="False" />
        <asp:BoundField DataField="CompanyName" HeaderText="CompanyName"  />
    </Columns>
</asp:GridView>

At ASPX.CS

private List<int> ProductIDs
{
    get
    {
        if (this.ViewState["ProductIDs"] == null)
        {
            this.ViewState["ProductIDs"] = new List<int>();
        }
        return this.ViewState["ProductIDs"] as List<int>;
    }
}

private List<string> CustomerIDs
{
    get
    {
        if (this.ViewState["CustomerIDs"] == null)
        {
            this.ViewState["CustomerIDs"] = new List<string>();
        }
        return this.ViewState["CustomerIDs"] as List<string>;
    }
}

protected void Page_Load(object sender, EventArgs e)
{
    if (!IsPostBack)
    {
        BindGrid(gvProducts, "Products");
        BindGrid(gvCustomers, "Customers");
    }
}

protected void gvProducts_PageIndexChanging(object sender, GridViewPageEventArgs e)
{
    foreach (GridViewRow gvr in gvProducts.Rows)
    {
        CheckBox chkSelect = gvr.FindControl("chkSelect") as CheckBox;
        if (chkSelect != null)
        {
            int productID = Convert.ToInt32(gvProducts.DataKeys[gvr.RowIndex]["ProductID"]);
            if (chkSelect.Checked && !this.ProductIDs.Contains(productID))
            {
                this.ProductIDs.Add(productID);
            }
            else if (!chkSelect.Checked && this.ProductIDs.Contains(productID))
            {
                this.ProductIDs.Remove(productID);
            }
        }
    }
    gvProducts.PageIndex = e.NewPageIndex;
    BindGrid(gvProducts, "Products");
}

protected void gvProducts_RowDataBound(object sender, GridViewRowEventArgs e)
{
    GridViewRow gvr = e.Row;
    if (gvr.RowType == DataControlRowType.DataRow)
    {
        CheckBox chkSelect = gvr.FindControl("chkSelect") as CheckBox;
        if (chkSelect != null)
        {
            int productID = Convert.ToInt32(gvProducts.DataKeys[gvr.RowIndex]["ProductID"]);
            chkSelect.Checked = this.ProductIDs.Contains(productID);
        }
    }
}

protected void gvCustomers_PageIndexChanging(object sender, GridViewPageEventArgs e)
{
    foreach (GridViewRow gvr in gvCustomers.Rows)
    {
        CheckBox chkSelect = gvr.FindControl("chkSelect") as CheckBox;
        if (chkSelect != null)
        {
            string customerID = gvCustomers.DataKeys[gvr.RowIndex]["CustomerID"].ToString();
            if (chkSelect.Checked && !this.CustomerIDs.Contains(customerID))
            {
                this.CustomerIDs.Add(customerID);
            }
            else if (!chkSelect.Checked && this.CustomerIDs.Contains(customerID))
            {
                this.CustomerIDs.Remove(customerID);
            }
        }
    }
    gvCustomers.PageIndex = e.NewPageIndex;
    BindGrid(gvCustomers, "Customers");
}

protected void gvCustomers_RowDataBound(object sender, GridViewRowEventArgs e)
{
    GridViewRow gvr = e.Row;
    if (gvr.RowType == DataControlRowType.DataRow)
    {
        CheckBox chkSelect = gvr.FindControl("chkSelect") as CheckBox;
        if (chkSelect != null)
        {
            string customerID = gvCustomers.DataKeys[gvr.RowIndex]["CustomerID"].ToString();
            chkSelect.Checked = this.CustomerIDs.Contains(customerID);
        }
    }
}

private DataTable PopulateData(string tableName)
{
    DataTable dt = new DataTable();
    using (SqlConnection conn = new SqlConnection(ConfigurationManager.ConnectionStrings["NorthwindConnectionString"].ConnectionString))
    {
        string sql = String.Format("SELECT * FROM {0}", tableName);
        using (SqlDataAdapter adap = new SqlDataAdapter(sql, conn))
        {
            adap.Fill(dt);
        }
    }
    return dt;
}

private void BindGrid(GridView gvTemp, string tableName)
{
    gvTemp.DataSource = PopulateData(tableName);
    gvTemp.DataBind();
}

Happy Coding!

P.S: Database in use is Northwind Sample Database.
Read more...

Insert Arabic Words into Database

0 comments
Often at forums.asp.net we come across the problem that occurs while inserting foreign language to the database. Supopose I wanted to insert 'اتصالات' to a table named 'table_test'. When I look at the entry at all I see is ?????.

Why did this happen? Its because the field we enter the data needs to be having COLLATE Arabic.

To understand that we must first understand what collation is.

What is collation?

Collation refers to a set of rules that determine how data is sorted and compared.
Character data is sorted using rules that define the correct character sequence,
with options for specifying
1) case-sensitivity,
2) accent marks,
3) kana character types and
4)character width.

Case sensitivity

If A and a, B and b, etc. are treated in the same way then it is case-insensitive. A computer treats A and a differently because it uses ASCII code to differentiate the input. The ASCII value of A is 65, while a is 97. The ASCII value of B is 66 and b is 98.

Accent sensitivity

If a and á, o and ó are treated in the same way, then it is accent-insensitive. A computer treats a and á differently because it uses ASCII code for differentiating the input. The ASCII value of a is 97 and áis 225. The ASCII value of o is 111 and ó is 243.

Kana Sensitivity

When Japanese kana characters Hiragana and Katakana are treated differently, it is called Kana sensitive.

Width sensitivity

When a single-byte character (half-width) and the same character when represented as a double-byte character (full-width) are treated differently then it is width sensitive.

Now we have identified the problem. Lets try to solve it using an example.
In this example I am saving a textbox value to database on the click of a button.

Suppose I have a table named table_test with two columns
1. [myid] int auto
2. [mytext] nvarchar(50)

I want to enter the arabic word to the field mytext.

Step1
At Database provide collate to the field on which we want to insert the arabic word
ALTER TABLE test_table
ALTER COLUMN mytext VARCHAR(50) COLLATE Arabic_CI_AI
Step 2
protected void myButton_Click(object sender, EventArgs e)
{
    using (SqlConnection conn = new SqlConnection(ConfigurationManager.ConnectionStrings["forums_ConnectionString"].ConnectionString))
    {
        conn.Open();
        string sql = String.Format("INSERT INTO test_table (mytext) VALUES (N'{0}')",
            mytext.Text.Trim());
        using (SqlCommand cmd = new SqlCommand(sql, conn))
        {
            cmd.ExecuteNonQuery();
        }
    }
}
Please note that I have put N' before the value.
Read the article Why do some SQL strings have an 'N' prefix? if you want to know its significance.
Read more...

Tuesday, November 16, 2010

Prevent site from getting loaded on iframe

0 comments
What if somebody loads your obfuscated fancy javascript or AJAX methods to drive traffic to their site utilising your bandwidth? Here is a simple solution in javascript.

<script type="text/javascript">
//<![CDATA[
    if (window.top !== window.self) {
        document.write = "";
        window.top.location = window.self.location;
        setTimeout(function () {
            document.body.innerHTML = '';
        }, 1);
        window.self.onload = function (evt) {
            document.body.innerHTML = '';
        }; 
    }
//]]>
</script>


Paste that javascript snippet inside your head tag of your html.
Twitter(Dustin Diaz) uses that at the Twitter Profile Widget Page. :(
I found it the hard way (lol). Way to go Dustin!
Read more...

Monday, November 15, 2010

HTML Encode Decode in Javascript/jQuery

0 comments
Last day, I had a resolute and unyielding need to HTML Decode a string.
I saw many solutions but was not satisfied.
Then I found the StackOverFlow reference which is the most optimal solution I have seen till date. Just pasting it here for easy reference.

function htmlEncode(value){ 
  return $('<div/>').text(value).html(); 
} 

function htmlDecode(value){ 
  return $('<div/>').html(value).text(); 
}


Did I say jQuery? I sure did say optimal :P
Happy Coding!

Dependency: jQuery
Read more...

Wednesday, November 10, 2010

Different ways to create a DataTable and set Schema

0 comments
Was hanging out StackOverflow and I saw Marc Gravell initializing the DataTable in a simpler and cleaner way. Here goes

DataTable dataTable = new DataTable
{
    Columns = {
        {"ID", typeof(int)},
        {"Name", typeof(string)},
        "Location"
    },
    TableName="NaveenTest"
};
dataTable.Rows.Add(1, "Naveen", "Coder");

Please note that if you don't specify the type it will automatically be converted to string. See how "Location" is initialised
And my old method

DataTable dtOld = new DataTable("NaveenTest");
dtOld.Columns.Add("MyID", typeof(int));
dtOld.Columns.Add("Name");
dtOld.Columns.Add("Location");
DataRow drOld = new DataRow();
drOld[0] = 1;
drOld[1] = "Naveen";
drOld[2] = "Coder";
dtOld.Rows.Add(drOld);

Aaarghhh...

A lot cleaner!
What do you say?
Read more...