Tuesday, September 29, 2009

Using jQuery with the BlockUI Plugin And LINQ to SQL

Using jQuery with the BlockUI Plugin And LINQ to SQL
 
There are quite a few jQuery Plugin’s out on the internet, and one of the cooler ones I’ve come across lately is the BlockUI Plugin. The BlockUI Plugin lets you simulate synchronous behaviour when using AJAX, without locking the browser. When activated, it will prevent user activity with the page (or part of the page) until it is deactivated. BlockUI adds elements to the DOM to give it both the appearance and behaviour of blocking user interaction.
Before we get started, this example uses the latest version of jQuery which is 1.3.2. That can be downloaded from here. You’ll also need a copy of the Northwind database. If you don’t have a copy of the Northwind database, you can go here to download it. 
The BlockUI Plugin has a couple of options that you can override to change the default behaviour and style. The options I am overriding in this example are:
  • css – style for the message when blocking
  • overlayCSS – style for the overlay
  • message – the message to display in the overlay
  • bindEvents - enable if you want key and mouse events to be disabled for content that is blocked
 
To make this example more life like I’m going to create a page where the user can type in a customer’s name and have it search the Northwind database and display the results all using jQuery and the BlockUI Plugin. The Plugin will give the user visual feedback immediately that their query is working.
Open Visual Studio 2008 and create a new Web Application. Add a new LINQ to SQL file to the project and call it Northwind. Add the customers table to the file:
Customer
The next step is to open the Default.aspx.cs file and add the following code:
C#
[WebMethod]
public static List<Customer> FetchCustomers(string contactName)
{
var customers = new List<Customer>();
      using (var dc = new NorthwindDataContext() )
      {
            customers = (from p in dc.Customers
                  where p.ContactName.StartsWith(contactName)
                  select p).ToList();
}
 
      for (int i = 0; i < 1; i++)
      {               
            Thread.Sleep(1000);
}
      return customers;
VB.NET
_
Public Shared Function FetchCustomers(ByVal contactName As String) As List(Of Customer)
Dim customers = New List(Of Customer)()
       Using dc = New NorthwindDataContext()
             customers = ( _
                  From p In dc.Customers _
                  Where p.ContactName.StartsWith(contactName) _
                  Select p).ToList()
        End Using
 
       For i As Integer = 0 To 0
             Thread.Sleep(1000)
       Next i
       Return customers
End Function
The code above will be called by jQuery. It searches the customer table for all the records that have a contact name that starts with what the user types in. For demonstration purposes I have added code in the method to mimic latency. Open the Default.aspx page and add the following jQuery code to the section of the page. Ideally JavaScript should go to a separate .js file, however for this example; I’ll keep it in the same page:
<head runat="server">
    <title>jQuery BlockUI Plugin with LINQ to SQLtitle>
    <script language="javascript" type="text/javascript" src="Scripts/jquery-1.3.2.js">script>
    <script language="javascript" type="text/javascript" src="Scripts/jquery.blockUI.js?v2.24">script>
    <script language="javascript" type="text/javascript">
        $(document).ready(function() {
            $('#btnFetchData').click(function() {
                $.blockUI({
                    css: {
                        padding: 0,
                        margin: 0,
                        width: '30%',
                        top: '40%',
                        left: '35%',
                        textAlign: 'center',
                        color: '#000000',
                        border: '3px solid #aaa',
                        backgroundColor: '#ffffff',
                        cursor: 'wait'
                    },
                    // styles for the overlay
                    overlayCSS: {
                        backgroundColor: '#000',
                        opacity: 0.6
                    },
                    message: ' Searching the database. Please  wait.',
                    bindEvents: true
                });
                $.ajax({
                    type: "POST",
                    url: "Default.aspx/FetchCustomers",
                    data: "{contactName:\"" + $("#txtContactName").val() + "\"}",
                    contentType: "application/json; charset=utf-8",
                    dataType: "json",
                    async: true,
                    cache: false,
                    success: function(msg) {
                        $.unblockUI();
                        var customers = msg.d;
                        if (customers.length > 0) {
                            $("#result").text("");
                            for (var i = 0; i < customers.length; i++) {
                                $("#result").append(customers[i].CustomerID + ", ");
                                $("#result").append(customers[i].CompanyName + ", ");
                                $("#result").append(customers[i].ContactName + ", ");
                                $("#result").append(customers[i].ContactTitle + ", ");
                                $("#result").append(customers[i].Address + ", ");
                                $("#result").append(customers[i].City + ", ");
                                $("#result").append(customers[i].Region + "
"
);
                            }
                        }
                        else {
                            // validation failed
                            $("#result").text("No matching records were found.");
                        }
                    },
                    error: function(XMLHttpRequest, textStatus, errorThrown) {
                        $.unblockUI();
                        alert(textStatus);
                    }
                });
                return false;
            });
        });     
    script>
head>
 
In the code above I am binding to the input button’s click event. When the user clicks the button, it will run the blockUI function immediately letting the user know their search is underway. Once the UI is blocked it will execute the FetchCustomers method. The data being returned is a generic customer list, so a check against the length property is required. 
var customers = msg.d;
if (customers.length > 0)
A
element named results will contain either the customers found, or a message letting the user know there were no matching records. If you run the application and search for a customer, you’ll see the UI is blocked and a message appears whilst searching.
SearchingDatabase
This functionality would also be useful for collecting data and performing server side validation on that data. This is yet another good use of jQuery.
The entire source code of this article can be downloaded over here

Wednesday, September 16, 2009

Deploying ASP.NET Applications

This article covers how to deploy ASP।NET Application in the production environment. It takes you through some of the concepts like application pool, why we need it and Configuring Application pools. At the end the author discusses some of the common problems that may arise during deployment and the possible solutions to overcome them.

Introduction


As an ASP.NET

developer, we are always focusing on learning new ideas on design and development which made us to have less knowledge on deployment of applications in production. This article targets developer community to have some of the rudimentary knowledge on deployment of ASP.NET application on IIS 6.0. After reading this article a user will be familiar in:

· Virtual Directories and Creating it

· Application Pools, Creating Application Pools and why it is used

· Use of service accounts in Application Pools

· Web.Config Settings and using Web.Config Settings for debugging errors

· Common hindrance we may possibly face during deployment and resolutions

It is assumed that the user is logged in to the server or connected to the server through Remote Desktop Connection and the user has enough permission to do the deployment.

Preparing the application for deployment


We can use the Web Deployment plug-in for Visual studio 2005 given by Microsoft for creating Web deployment projects for 2.0 Applications, where we can compile in release mode for 1.1 applications for deployment. See the reference section for more details on Web Deployment plug-in. Copy the application to a folder location where the application needs to be deployed on the server. Make all Web.Config changes, like updating connection strings, if there is any appsettings values changes corresponding to production environments, etc.

Virtual Directory

An IIS Virtual Directory is essentially an alias to the physical directory. The IIS Virtual Directory is a directory name which may be accessed from the Internet to access the physical directory on the server.

The most common ways of creating virtual directory is done through two methods.

1. Using IIS Manager

2. Using Windows Explorer

Using IIS Manager

We can open IIS manager in 3 ways:

· Type Inetmgr in RUN

· Open Control Panel > Administrative tools > Internet Information Services

· Right click My Computer, click Manage and expand Internet Information Services

Creation

Doing any of the above approach will bring us the IIS manager.

1. Expand the local computer node, right click the Website under which you want to deploy the application and click New > Virtual Directory. It will bring a dialog like Figure 1.

Figure 1 - Create Virtual Directory

Click Next.

2. It will bring the next window for entering “Alias” for our websites. See Figure 2.

Figure 2 - Virtual Directory Alias

Type the alias name you would like to assign for the applications virtual directory. I have used “test” for this article. Click Next.

3. It will bring a window for linking our website's physical directory with virtual directory.

Figure 3 - Physical Directory Path

Browse to the location and select the website folder. Click Next.

4. This will bring the window for specifying access permissions for the users. Select appropriate permissions.

Figure 4 - Virtual Directory Access Permission

I have not changed the default setting in this window as this permission is more than enough to run most of the applications. Click Next.

5. Click Finish. Thus we have created the virtual directory.

Using Windows Explorer

1. Browse to the folder location where you copied the application and right click the folder and click “Sharing and security.”

2. Open “Web Sharing” tab and select “Share this folder” which will ask for the Alias. Type an Alias name, click OK and click OK again. We have created virtual directory through windows explorer.

Configure ASP.NET version

Sometimes the server we are deploying may have both 1.1 and 2.0 framework installed. So we need to configure the applications to use appropriate framework. It can be done through the ASP.NET tab of virtual directory property box like in Figure 5.

Figure 5 - ASP.NET version picker

If it is 2.0 Application, select 2.0.xxxxx version or else 1.1.xxxx.

Application Pools


Application Pools or App Pools are introduced with IIS 6.0 to isolate websites into a group called Application Pools. Also we can say application pools are a group of one or more URL's that are served by a worker process, meaning applications running in a single app pools run in the same worker process w3wp.exe, thus providing a boundary so that if one application fails it does not hinder other applications running on other app pools. So as a good practice a highly confidential, secured website can be assigned with a separate app pool. Also we can use app pools to troubleshoot applications by isolating them to a separate application pool if we suspect that it creates problem. By using an application pool, we can have specific configuration settings to a worker process that services a group of applications or single application that is running under the App Pool. For example, you can configure worker process recycling and several other configuration options to match the needs of each application. We will see this in detail in coming sections.

With this introduction to Application pools we will move to our subject matter, creating Application pools in IIS 6.0.

Creation

A new application pool can be created using IIS Manager.

Steps

1. Open IIS Manager.

2. Expand local computer node. Right click Application Pools node and click New> Application Pool like Figure 6.

Figure 6 - Creating New Application Pool

It will open a dialog to create new app pool.

Figure 7 - Application Pool ID

Type a Pool ID for the app pool, the best practice to give identity is choosing a name relevant to the applications hosted. For example, if the app pool hosts a Shopping cart site, let the pool identity be ShoppingCartPool so that it can be easily identified as opposed to AppPool #1, 2, etc. Under Application pool settings> select “Use default settings for new application pool,” Selecting “Use existing application pool as template” will prompt as to select an existing app pool as the template so that same setting is applied for the newly created app pool.

3. Click OK. A new application pool is created with default configurations.

Customizing Application pools

By default, Application pools are configured to use Network Service Account to service the request. At times we will end in a situation where we should use a separate account for servicing the request for different reasons. There are other configuration settings which some times need to be optimized, which are really done in exceptional situations. The coming sections will answer these things and take us through accomplishing this.

Steps

1. Right click the Application pool you have created (Test Pool) in this example and click Properties. It will bring up a dialog like the one below.

Figure 8 - Application Pool Property recycling tab

Recycling tab is opened with default settings. Periodic recycling of your application pools is recommended to help to clean up memory fragmentation, memory leaks, abandoned threads and other disorders. Keep in mind that when an application pool recycles, session state information stored in-process is lost for that pool, but other pools are not affected. ASP.NET, however, does allow you to store your session state outside the worker process, so that session information is not lost during a recycle. We can recycle the worker process based on the number of requests and memory usages.

2. Moving to Performance tab. Refer to Figure 9.

Figure 9 - Application Pool Property Performance tab

When the application does not receive a request for certain amount of time, it is said to be idle so this setting allow us to free up the occupied resource from the server after the specified time given here. Consider changing the Request queue limit if your application receives thousands request per second to mitigate Server busy messages. Most of the time Enable CPU monitoring is not used. Web garden setting should not be changed from 1, this specifies the number of worker process required to process the request for an app pool.

3. Next, tab "Health" tab for configuring the health, i.e. the availability of the application can be configured. Refer to Figure 10.

Figure 10 - Application Pool Property Health tab

Enable pinging causes IIS to automatically query a worker process to see if it is responsive and utilizing network bandwidth. Enable rapid-fail protection helps to disable the app pool for specified number of failures occurred in the worker process. Startup time limit and shutdown time limit are self explanatory and failing to satisfy those condition falls under failure for rapid fail protection.

4. The "Identity" tab is where we can configure the worker process identity.

Figure 11 - Application Pool Property Identity tab

The predefined setting’s default is to use network service account which is a less privileged account for security purposes. The other account that can be preconfigured is Local Service and LocalSystem account. Before making the App pool to use custom account known as Service accounts, we will explore what and why it is used.

Service Accounts

It is the identity of the App pool under which it services the request. It is the account that has very less privileges on the machine so as to reduce the security risk and loop holes. There can be several reasons to opt for custom service account over the Network service account. Some of the reasons are:

· We can have different access controls for different applications on the local and network resources such as fileservers, etc.

· It is also a mode of isolating one application from another by giving a separate identity so other applications cannot access the resource of another application.

· We can prevent any accidental or deliberate changes to the access controls or permissions associated with the general purpose Network Service account from affecting your application.

See reference section for creating new service accounts.

One think to note here is if our site uses a database then make sure that the custom service account has the required access to the database.

Configuring Custom service account with Application Pool

In the above Figure select Configurable> type the service account id, password and enter. It will ask for password confirmation like the figure below. Click OK.

Figure 12 - Configure service account

After doing this restart the App pool by stopping and starting it again.

Associating Site with Application Pool

We need to associate our site with the App pool we created. It can be done by right clicking the site's virtual directory (Test in our case) and property. Select the TestPool from Application pool drop down in "Home Directory" tab as in Figure 13. Click Apply and OK.

Figure 13 - Associating site with Application Pool

We are at the end of the process and we need to do a smoke test for the application verification.

Possible Errors


Error

Service unavailable

Resolution

This is one of the ever green errors we often used to get mostly because of service accounts. The common problem will be this account might not be a member of IIS_WPG group on the server or check IIS_WPG group have Read & Execute, List Folder Contents, and Read permissions to the Web site directories. So precheck with a network admin who is creating the service account for you whether the account has all the required permissions on the server.

Error

An error has occurred while establishing a connection to the server. When connecting to SQL Server 2005, this failure may be caused by the fact that under the default settings SQL Server does not allow remote connections. (Provider: TCP Provider, error: 0 - A connection attempt failed because the connected party did not properly respond after a period of time, or established connection failed because connected host has failed to respond.)

Resolution

Again, there may be several reasons, the most common is checking if the service account has access to the SQL Server. This error occurs even if you are not using SQL Server 2005, i.e. the same error occurs even if you use SQL Server 2000. Similar error occurs if there is any problem in the connection string too.

Error

It is not possible to run different versions of ASP.NET in the same IIS process. Please use the IIS Administration Tool to reconfigure your server to run the application in a separate process.

Resolution

When we host multiple versions of ASP.net in a single server, we may get this error in event log. The problem might be an application pool will be associated with 2 different applications that use different frameworks. So isolating this application into a different App Pools will solve the problem.

Points to note


This section highlights some of the important things to consider when we are deploying the application.

1. Make sure the Web.Config setting is perfect, such as connection strings, App setting values, check because setting it to true causes the application to be processed slow, memory consumption is more, scripts and images downloaded from the WebResources.axd handler are not cached.

2. To trouble shoot the error if it occurred use section in Web.Config and make sure you are reverting back to the original settings.

3. If we are running multiple versions of ASP.net on the same webserver do not use aspnet_regiis utility with –i switch to register the ASP.net with the IIS, instead use –s switch and register it for the particular site because using –i switch is going to update the entire IIS with the current version of ASP.net you are registering leaving the existing application configuration affected. For example, Aspnet_regiis –s W3SVC/1/ROOT/Test.

4. By default, IIS does not allow dynamic contents like ASP\ASP.NET to be processed by IIS. So to allow this, Open IIS manager, click Web Service Extensions and Allow the Web Service Extensions if it is disabled as shown in Figure 14. If there is no extensions for processing ASP.net 2.0 application, we can add a new web service extension by clicking "Add a new Web service extension" link. Read more on MSDN on how to add web service extensions in IIS 6.0.

Figure 14 - Web service Extensions



Conclusion

As a web developer we should have the rudimentary knowledge of deploying the web application in the production and so this article will fulfill this anticipation. Checkout Microsoft’s KB articles for more support on Errors and resolutions. Happy Coding!!!

ScriptManager Control Overview

ScriptManager Control Overview

Introduction

The ScriptManager control manages client script for Microsoft ASP.NET AJAX pages. By default, the ScriptManager control registers the script for the Microsoft AJAX Library with the page. This enables client script to use the type system extensions and to support features such as partial-page rendering and Web-service calls.

This topic contains the following sections:

Why Use the ScriptManager Control

You must use a ScriptManager control on a page to enable the following features of ASP.NET AJAX:

  • Client-script functionality of the Microsoft AJAX Library, and any custom script that you want to send to the browser. For more information, see ASP.NET AJAX and JavaScript.

  • Partial-page rendering, which enables regions on the page to be independently refreshed without a postback. The ASP.NET AJAX UpdatePanel, UpdateProgress, and Timer controls require a ScriptManager control to support partial-page rendering.

  • JavaScript proxy classes for Web services, which enable you to use client script to access Web services by exposing Web services as strongly typed objects.

  • JavaScript classes to access ASP.NET authentication and profile application services.

Enabling Partial-Page Rendering

When a page contains one or more UpdatePanel controls, the ScriptManager control manages partial-page rendering in the browser. The control interacts with the page life cycle to update the parts of the page that are inside UpdatePanel controls. For more information, see Partial-Page Rendering Overview.

The EnablePartialRendering property of the ScriptManager control determines whether a page participates in partial-page updates. By default, the EnablePartialRendering property is true. Therefore, partial-page rendering is enabled by default when you add a ScriptManager control to the page. For information about how to use the UpdatePanel control with the ScriptManager control, see Introduction to the UpdatePanel Control and Creating a Simple ASP.NET Page with Multiple UpdatePanel Controls.

Handling Errors

During partial-page rendering, you can handle errors by doing the following:

  • Set the AllowCustomErrorsRedirect property, which determines how the custom error section of the Web.config file is used when an error occurs during an asynchronous postback.

  • Handle the ScriptManager control's AsyncPostBackError event, which is raised when there is a page error during an asynchronous postback.

  • Set the AsyncPostBackErrorMessage property, which is the error message that is sent to the browser.

Using Type System Extensions

Microsoft AJAX Library adds type-system extensions to JavaScript that provide namespaces, inheritance, interfaces, enumerations, reflection, and helper functions for strings and arrays. These extensions provide functionality in client script that is like that of the .NET Framework. They enable you to write ASP.NET 2.0 AJAX Extensions applications in a structured way that improves maintainability, makes it easier to add features, and makes it easier to layer functionality. Adding a ScriptManager control to an ASP.NET Web page automatically includes the type-system extensions so that you can use the library in client script. For more information, see Extending JavaScript with ASP.NET AJAX.

Registering Custom Script

Use the ScriptManager control to manage resources that you have created for controls that participate in partial-page updates. Resources include scripts, styles, hidden fields, and arrays. The Scripts collection of the ScriptManager control contains a ScriptReference object for each script that is available to the browser. You can specify the scripts declaratively or programmatically.

The ScriptManager control also exposes registration methods that you can use to manage client script and hidden fields programmatically. When you are registering script or hidden fields that support partial-page updates, you must call registration methods of the ScriptManager control. (To register scripts that are not needed for partial-page updates, you use methods of the ClientScriptManager class.)

note

Any scripts on the page that are registered with the ScriptManager control and all event-handling script must be inside the

element on the page. Otherwise the script will not be registered or executed.

For a list of the ClientScriptManager controls registration methods, see Creating Custom Client Script in ASP.NET AJAX and the ClientScriptManager class overview.

Registering Web Services

The ScriptManager control's Services collection contains a ServiceReference object for each Web service that is registered with the ScriptManager control. The ASP.NET AJAX framework generates a client proxy object for each ServiceReference object in the Services collection. The proxy classes and their strongly typed members simplify using Web services from client script.

You can programmatically add ServiceReference objects to the Services collection to register Web services at run time. For more information, see Web Services.

Using Authentication and Profile Services from Client Script

The Microsoft AJAX Library includes proxy classes for calling the ASP.NET 2.0 forms authentication and profile application services directly from JavaScript. If you want to use a custom authentication service, you can register it using the ScriptManager control. For more information, see ASP.NET Application Services.

The ScriptManagerProxy Class

Only one instance of the ScriptManager control can be added to the page. The page can include the control directly, or indirectly inside a nested component such as a user control, content page for a master page, or nested master page. In cases where a ScriptManager control is already on the page but a nested or parent component needs additional features of the ScriptManager control, the component can include a ScriptManagerProxy control. For example, the ScriptManagerProxy control enables you to add scripts and services that are specific to nested components.

Class Reference

Class

Description

ScriptManager

A server control that makes script resources available to the browser, including the Microsoft AJAX Library and the functionality that enables partial-page rendering.

ScriptManagerProxy

A server control that enables nested components to add script and service references if the page already contains a ScriptManager control.

Tuesday, September 15, 2009

Themes and Skins in ASP.Net 2.0

Themes and Skins give a consistent look and feel for an application, whether it is a desktop application or a web application. The themes and skins for an application should allow customization, so that it can be changed according to the user’s preferences. ASP.Net 2.0 also provides features which can be used by any user to change the look and feel of the web application. ASP.Net 2.0 ships with themes like BasicBlue and SmokeAndGlass. The themes in ASP.Net 2.0 are stored in a folder called Themes.

Themes give a consistent look for all the pages within a web application. Themes consist of Skins, which contain the details of the styles that are applied to the controls in a page. A theme can have any number of skins. You can either use the themes available in ASP.Net 2.0 or create your own themes for your project.


To add a theme for a particular page you have to use the ‘Theme’ attribute in the Page directive of an .aspx page. For example, if you want to add the BasicBlue theme for a particular page, the page directive for that page would look like,

<%@Page Language="VB" Theme="BasicBlue" %>

The above line of code makes all the controls in a particular page follow the theme BasicBlue. It is also possible to make all the pages of a web application to have a consistent look. A theme can also be applied to all the applications in a server. To apply a theme for all the pages of an application the theme has to be declared in the web.config file of the application. The following code in the web.config file applies the theme BasicBlue at the application level, for all the pages of the application.





Once you state the theme at the application level in the web.config file, it is not necessary to give it in all the pages of the application. If you do not want the theme to be applied to a particular page, you can do so, by disabling the theme for that particular page alone. This can be done by making the ‘EnableTheming’ attribute of the page directive to False.

To apply theme for all the applications in a server, you need to declare the theme in the machine.config file. Declaring a theme in the machine.config file applies that theme to all the applications in the server. The code below shows, how to apply the theme for all the applications in a server. This code has to be there in the machine.config file.

...
...
theme="BasicBlue" >...

If you want to avoid applying a theme, declared in the machine.config file, for a particular application, you can do so by using the following code in the web.config file for that application.





You can create your own themes for an application. To create your own theme, you need to create skins. Skins are just CSS applied to the controls in a page. The file in which the CSS for the controls are given, should have an extension “.skin”. Skins are usually created in a Themes folder within the projects folder for an application. You can see the Themes folder in the Solution Explorer in Visual Studio .Net. The themes folder will have a folder icon with a brush. Within the Themes folder you can create different themes in separate sub-folders which contain the .skin files.

To create a skin for a label control, the skin file would have the code like,

Font-Size="Small" />

The above will make a label control to have Blue color fonts in it and the Font type would be Arial and of size Small. To apply this skin to all the label controls of a particular page you have to declare the theme of this skin at the page level in the page directive. If you have many skins for a particular theme and you want to apply a particular skin for a single label control, you can do so by using the SkinID attribute of that control. The following code applies a skin for a single textbox control:

SkinId="SkinName">Textbox1

Apart from applying themes at the page level, application level, and server level in design time, ASP.Net 2.0 allows you to apply themes to your aspx pages during runtime. You can access the Page.Theme property in your code to specify a particular theme during runtime. If you are changing the theme for a particular page during runtime, it is advised to change the theme in the Page_PreInit event, as themes are applied to the page before the occurrence of the post back event for

Monday, September 14, 2009

How to Display Row icons in DataGridView

Level: Intermediate
Knowledge Required:

  • DataGridView Control
  • Data Bindings
  • DataGridView Columns

Description:

We usually use DataGridView control to display contents of a DataTable. For a good impression and User Friendly Interface, we display an Icon with each Row in the DataGridView. For Example we can have a DataTable to store Tasks. Each task can have Status = Done / NOT Done. So we want that when we display these tasks in the DataGridView control there should be an Icon representing the Status of Task. As shown in the following figure.


DataGridView Control with Row Status Icon

To get the above result we will add an Unbound Column in the DataGridView control of Type DataGridViewImageColumn and set the VirtualMode property of DataGridView control to True. This will cause the DataGridView to fire the CellValueNeeded event. This Event triggers whenever the Cell is going to be rendered. Note that only the Unbound Cell will cause this event to be triggered. The bound columns will render themselve automatically.

For this purpose we first have created a Typed DataSet i.e. TaskDataSet containing a DataTable Task as,

Task DataTable

In the above table Task_Status is an Int32 field. We have decided that when this field is 0 (zero) then it means task is NOT Done yet and if this field contains 1 then it means task is Done.

Next we will create a Form and will put the following things:

  • TaskDataSet
  • BindingSource
  • DataGridView Control

Then we will bind the DataGridView to the BindingSource.

After this we will setup our DataGridView control by removing the Columns: Task_ID and Task_Status then we will add an Unbound Column TaskStatusIconColumn of type DataGridViewImageColumn. This column should be the first column of DataGridView set its properties as,

Properties of TaskStatusIconColumn:

  • DefaultCellStyle:
    • BackColor = White
    • ForeColor = Black
    • SelectionBackColor = White
    • SelectedForeColor = Black
  • Resizable = False
  • Width = 32

Now set the properties of Task_Description column which should have the Name TaskDescriptionDataGridViewTextBoxColumn.

Properties of TaskDescriptionDataGridViewTextBoxColumn:

  • AutoSizeMode = Fill

Properties of DataGridView Control:

  • RowHeadersVisible = False
  • SelectionMode = FullRowSelect
  • VirtualMode = True

VirtualMode is an important property here which must be True otherwise the CellValueNeeded event will NOT be triggered. And finally in the CellValueNeeded Event Handler we will use the following code:

Private Sub TaskDataGridView_CellValueNeeded(ByVal sender As Object, ByVal e As System.Windows.Forms.DataGridViewCellValueEventArgs) Handles TaskDataGridView.CellValueNeeded
If e.RowIndex >= 0 AndAlso e.ColumnIndex = Me.TaskStatusIconColumn.Index Then
Dim drvTask As DataRowView
Dim rowTask As TaskDataSet.TaskRow
drvTask = Me.TaskDataGridView.Rows(e.RowIndex).DataBoundItem
rowTask = CType(drvTask.Row, TaskDataSet.TaskRow)
Select Case rowTask.Task_Status
Case 0 ' NOT Done
e.Value = My.Resources.Resources.Blank16
Case 1 ' Done
e.Value = My.Resources.Resources.OK
End Select
End If
End Sub

In above code I have used a technique to get the DataRow of DataTable from DataGridView's Row. I have discussed this technique in my previous post How to Get the Table Row from DataGridView Row

Note that I have created 2 PNG images (Blank16 and OK) and have added them in my Resources. Blank16 is a Blank PNG if we dont use this, then DataGridView will render its default image i.e. a Red Cross

You can download the source from here:

DataGridViewRowStatusIcon.rar