Blog Archives

ASP.Net: Disable TabIndex Focusing

If you need to disable/restrict focusing on one or more controls in a page then just mention TabIndex=”-1″.

This is useful particularly when you have some read only controls in your WebForm and you don’t want the control to move(focus) to those controls.

This is known to most of the web-developers but hopefully it will be useful to others.

Javascript: Thousand separator

We may use following javascript function to show numbers formatted with thousands separator.

Definition


function formatThousandPlace(orgNum) {
            arr = orgNum.split('.');    //split integer part & fractional part
            intPart = arr[0];           //store integer part in a variable
            fractionPart = arr.length > 1 ? '.' + arr[1] : '';  //store fractional part in a variable
            var rgx = /(\d+)(\d{3})/;   //regexp to find thousand place
            while (rgx.test(intPart)) { 
                intPart = intPart.replace(rgx, '$1' + ',' + '$2');  //replace integer part after inserting a comma in the thousandth place
            }
            document.write(intPart + fractionPart); //write final value to the document
        }

Function Call
Now, we can use it anywhere in the document where we want to show those numbers. For example: it may inside normal html elements or some dynamic ASP.Net controls like GridView, DataList, FormView etc.

<script language="javascript">formatThousandPlace('10000000.00')</script>

While calling this from ItemTemplate of an ASP GridView the syntax will be

<asp:TemplateField HeaderText="Price">
    <ItemTemplate>
       <script language="javascript">formatThousandPlace('<%#Eval("SalePrice") %>')</script>
    </ItemTemplate>
</asp:TemplateField>

I hope this is helpful.

ASP.Net : DropDownList containing category – sub category hierarchy

Introduction:

This article will provide us a way to embed both categories and sub-categories hierarchy in a single DropDownList exactly same as the image on the left.

I searched the web for this but did not find exactly what I needed. So, I planned to write my own logic for this. If somebody has a better idea then I really appreciate and request to share.

Description:

Lets take an example where we need to show states and districts of India in a single DropDownList with their hierarchy. Here state will behave as category and districts can be considered as sub-categories.

In DB part we need two tables i.e, States and Districts may be like following structure.

  • State       –> (StateId int pk, StateName varchar(50))
  • Districts –> (DistrictId int pk, StateId int fk, DistrictName varchar(50))

Or, this script may help you creating the tables


CREATE TABLE [dbo].[States](
 [StateId] [int] IDENTITY(1,1) NOT NULL,
 [StateName] [varchar](50) NULL,
 CONSTRAINT [PK_States] PRIMARY KEY CLUSTERED
(
 [StateId] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]

GO

CREATE TABLE [dbo].[Districts](
 [DistrictId] [int] IDENTITY(1,1) NOT NULL,
 [StateId] [int] NOT NULL,
 [DistrictName] [varchar](50) NULL,
 CONSTRAINT [PK_Districts] PRIMARY KEY CLUSTERED
(
 [DistrictId] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]

GO

ALTER TABLE [dbo].[Districts] WITH CHECK ADD CONSTRAINT [FK_Districts_States1] FOREIGN KEY([StateId])
REFERENCES [dbo].[States] ([StateId])
GO

ALTER TABLE [dbo].[Districts] CHECK CONSTRAINT [FK_Districts_States1]
GO

Now insert some sample data or you can execute this script.


/****** Object: Table [dbo].[States] ******/
SET IDENTITY_INSERT [dbo].[States] ON
INSERT [dbo].[States] ([StateId], [StateName]) VALUES (1, N'Odisha')
INSERT [dbo].[States] ([StateId], [StateName]) VALUES (2, N'West Bengal')
INSERT [dbo].[States] ([StateId], [StateName]) VALUES (3, N'Bihar')
INSERT [dbo].[States] ([StateId], [StateName]) VALUES (4, N'Jharkhand')
SET IDENTITY_INSERT [dbo].[States] OFF
/****** Object: Table [dbo].[Districts] ******/
SET IDENTITY_INSERT [dbo].[Districts] ON
INSERT [dbo].[Districts] ([DistrictId], [StateId], [DistrictName]) VALUES (1, 1, N'Mayurbhanj')
INSERT [dbo].[Districts] ([DistrictId], [StateId], [DistrictName]) VALUES (2, 1, N'Keonjhar')
INSERT [dbo].[Districts] ([DistrictId], [StateId], [DistrictName]) VALUES (3, 1, N'Khorda')
INSERT [dbo].[Districts] ([DistrictId], [StateId], [DistrictName]) VALUES (4, 1, N'Balasore')
INSERT [dbo].[Districts] ([DistrictId], [StateId], [DistrictName]) VALUES (5, 2, N'Hoogly')
INSERT [dbo].[Districts] ([DistrictId], [StateId], [DistrictName]) VALUES (6, 2, N'Howrah')
INSERT [dbo].[Districts] ([DistrictId], [StateId], [DistrictName]) VALUES (7, 2, N'Jalpaiguri')
INSERT [dbo].[Districts] ([DistrictId], [StateId], [DistrictName]) VALUES (8, 3, N'Aurangabad')
INSERT [dbo].[Districts] ([DistrictId], [StateId], [DistrictName]) VALUES (9, 3, N'Patna')
INSERT [dbo].[Districts] ([DistrictId], [StateId], [DistrictName]) VALUES (10, 4, N'Bokaro')
SET IDENTITY_INSERT [dbo].[Districts] OFF

Place a DropDownList in your page.


<asp:DropDownList ID="drpDistricts" runat="server"></asp:DropDownList>

Lastly do the coding required to bind the DropDownList. Things to remember are we have a single DropDownList and it should be meant for choosing a sub-category(District), which means categories should be disabled for clicking. Although there may be several ways like looping the sub-categories and inserting categories in-between etc. but, I personally prefer to query both of them in a single query.


SELECT '- '+DistrictName AS TextField,DistrictId AS ValueField,StateId FROM DBO.Districts UNION SELECT UPPER(StateName),0,StateId FROM dbo.States ORDER BY StateId,DistrictId

Put DataTextField =”TextField” and DataValueField=”ValueField”

Now, lets do the coding to disable the categories (States).



foreach (ListItem item in drpDistricts.Items)
 {
 if (item.Value.ToString() == "0")
 {
 item.Attributes.Add("Style", "color:maroon");
 item.Attributes.Add("Disabled", "true");
 }
 }

That’s all.
Thanks for reading.
Feedback or suggestion are most welcome.

ASP.Net: Download files from server with their original name

Introduction :

Purpose of writing this post is to share a way to resolve a very common but important issue with uploading-downloading file in ASP.Net. I don’t claim it to be the most efficient way but it works for me.

Problem:

While uploading a file to the server we may save it with its original file name and may code like-


FileUploader1.SaveAs(Server.MapPath("UploadedFiles/" + FileUploader1.FileName));

But, problem is if we upload another file with same name as previous file then the previous one will be replaced with the latest one. Now all the links for downloading both theses files will reference to the same file on the server.
Again we may resolve this issue by saving files with unique name on the server and may code like-

FileUploader1.SaveAs(Server.MapPath("UploadedFiles/" + DateTime.Now.ToString("yyyyMMddhhmmssfffffff") + System.IO.Path.GetExtension(FileUploader1.FileName);));

By doing this we will lose the original file name forever. But, in some or, more scenarios user may expect the file to be downloaded to his/her hard-disk with the original file name with which he/she uploaded the file to the server. (Example: Uploading-Downloading multiple resumes of a candidate).

We can solve this issue by storing both the names of a file i,e original & unique name on server.

The actual headache now comes in to picture. File is saved on the server with some unique name but we want the to change it’s name to the original name while user downloading it to his/her hard-disk.

Solution:

[View Demo]

The above said problem can be solved by following few steps. For the illustration I am taking a Gridview to show files for downloading and LinkButton for the download links.

  • Store both actual and unique names of the file in Database
  • Use a Hidden Field to store actual(unique) file name in the gridview
    <asp:TemplateField HeaderText="Uploaded File">
     <ItemTemplate>
     <asp:LinkButton ID="lnkDownload" Text='<%#Eval("FileNameOriginal")%>' runat="server" OnClick="lnkDownload_Click" />
     <asp:HiddenField ID="hfDownload" runat="server" Value='<%#Eval("FileNameActual")%>' />
     </ItemTemplate>
     </asp:TemplateField>
    
    
  • Now, put following code in the link button click event
    LinkButton lnkDwnload = (LinkButton)sender;
     GridViewRow grow = (GridViewRow)lnkDwnload.Parent.Parent;
     HiddenField hfDownload = (HiddenField)grow.FindControl("hfDownload");
     Response.AddHeader("Content-Disposition", "attachment;filename=" + lnkDwnload.Text);
     Response.ContentType = GetContentType(Server.MapPath("~/UploadedFiles/" + hfDownload.Value.ToString()));
     Response.TransmitFile(Server.MapPath("~/UploadedFiles/" + hfDownload.Value.ToString()));
     Response.End();
    
    

Note that I have used a method GetContentType() to get the content type/MIME type of the file to be downloaded.


private string GetContentType(string fileName)
 {
 string contentType = "application/octetstream";
 string ext = System.IO.Path.GetExtension(fileName).ToLower();
 Microsoft.Win32.RegistryKey registryKey = Microsoft.Win32.Registry.ClassesRoot.OpenSubKey(ext);
 if (registryKey != null && registryKey.GetValue("Content Type") != null)
 contentType = registryKey.GetValue("Content Type").ToString();
 return contentType;
 }

Note : Microsoft.Win32 is OS specific MSDN

For a universal solution we may use another way of getting the MIME type.


private string GetContentType(string fileName)
 {
 string ext = System.IO.Path.GetExtension(fileName).ToLower();
 switch (fileName)
 {

//add as many extensions of file types you expect to be uploaded

//for a complete list you may visit http://stackoverflow.com/questions/1029740/get-a-mime-from-an-extension

case ".doc": return "application/msword";

case ".docx": return "application/vnd.openxmlformats-officedocument.wordprocessingml.document";

case ".jpeg": return "image/jpeg";

case ".jpg": return "image/jpeg";

case ".bmp": return "image/bmp";

default: return "application/octet-stream";

}
}

Conclusion:

This works very fine for me. If you are facing problem then drop a comment, it will be my pleasure to help you. Any better idea is welcome.

Thanks for reading !

An alternate to CASE WHEN of SQL Server for few scenarios

Purpose of this quick post is to present an alternative way to CASE WHEN of SQL Server.

To execute the demonstration, take a look at the following example.


SELECT CustomerName,Address,Mobile FROM Customers ORDER BY CustomerName

This SQL query will retrieve the list of Customers from Customer table. Let Address and Mobile are the fields which allow NULL. It means the result of the query may return NULL for these two fields. Now we will use the result set returned by the above query to bind a Datalist or a Gridview.Let consider for Datalist, then we will use following code on .aspx page to bind these fields


Address : <%#DataBinder.Eval(Container.DataItem, "Address")%>

Mobile   :<%#DataBinder.Eval(Container.DataItem, "Mobile")%>

But, here problem is that when there is no data against one/both of these fields then on browser it will show nothing for the eval data. To avoid this we generally re-write the query using CASE WHEN as-


SELECT CustomerName,CASE WHEN Address IS NULL THEN '--Not Available--' ELSE  Address END AS  Address,CASE WHEN Mobile IS NULL THEN '--Not Available--' ELSE Mobile END AS Mobile FROM Customers ORDER BY CustomerName

The above query ensures that there is no blank space for the above said two field in the browser.

Now, for some scenario where I don’t want to set it from the server and I want an alternative then I may use Javascript to achieve this. Here the query will be same as the first query but change required on the .aspx code.

1.Declare a small Javascript method


function ReplaceEmptyFields(orig, repl) {

//orig : Origional string

//repl: String to be replaced with
 if (orig == "") {
 document.write(repl);
 }
 else {
 document.write(orig);
 }
 }

2.Call the above Javascript in place of Databinder as below

Address : <script language="javascript">ReplaceEmptyFields('<%#DataBinder.Eval(Container.DataItem, "Address")%>', "--Not Available--")</script>
Mobile : <script language="javascript">ReplaceEmptyFields('<%#DataBinder.Eval(Container.DataItem, "Mobile")%>', "--Not Available--")</script>

This will provide the same result as previous example using CASE WHEN. Few of the advantages of using this includes html formatting and style can be applied to the result. For example, if I’ll change the above code to show ‘–Not Available–’ in Gray color so that it will be more easy to read then the code on .aspx page will be like-


Address : <script language="javascript">ReplaceEmptyFields('<%#DataBinder.Eval(Container.DataItem, "Address")%>', "<font color='gray'>--Not Available--</font>")</script>
Mobile : <script language="javascript">ReplaceEmptyFields('<%#DataBinder.Eval(Container.DataItem, "Mobile")%>', "<font color='gray'>--Not Available--</font>")</script>

This post is based on my experience and experiments, so if you find something missing or, if you have a better idea then please share in  the comments.

Merge gridview cells in ASP.Net

PreRender Event of a control is a very useful event in ASP.Net. This is the event which will be called just before the control rendered to the client browser and modification done to the control in this stage of life cycle will reflect in the browser.

For example, lets take a gridview in to consideration. We know that a gridview always follows a columnar or tabular structure. Now one may ask -what is columnar or tabular structure..Ok, for now I am just sharing a line. Columnar structure means data in the gridview to be arranged only in a column basis view or table basis view. In fact when are binding a gridview, it is just rendering the rows present in the datasource in the manner we have defined its header cells. You can’t find a data of a column in  another column normally.

Yes, we are here to change this basic idea. We don’t have any real control to the structure of gridview till the Databinding event. Although we have certain process to change the structure of the gridview on RowDataBound, but I still feel it is more easy and convenient way to do the changes on gridview PreRender  event. The cause for suggesting this is- on this event we have a ready made structure and we need to check for necessary logic and do the changes.

For gridview cells merge, I am using following method to be called inside gridview PreRender event.

Here, the int array contains all the column indices that are to be merged on same data if found.


public void MergeCell(int[] colIndices)
{
foreach (int colIndex in colIndices)
{
for (int rowIndex = gvSchoolList.Rows.Count - 2; rowIndex >= 0; rowIndex--)
{
GridViewRow row = gvSchoolList.Rows[rowIndex];
GridViewRow previousRow = gvSchoolList.Rows[rowIndex + 1];
if (row.Cells[colIndex].Text == previousRow.Cells[colIndex].Text)
{
row.Cells[colIndex].RowSpan = previousRow.Cells[colIndex].RowSpan < 2 ? 2 : previousRow.Cells[colIndex].RowSpan + 1;
previousRow.Cells[colIndex].Visible = false;
}
}
}
}



And finally you will get a result like this-

Gridview with merged cells

Follow

Get every new post delivered to your Inbox.