Monday, June 18, 2007

Indexers in C#

C# introduces a new concept known as Indexers which are used for treating an object as an array. The indexers are usually known as smart arrays in C# community. Defining a C# indexer is much like defining properties. We can say that an indexer is a member that enables an object to be indexed in the same way as an array.

this [argument list]
{
get
{
// Get codes goes here
}
set
{
// Set codes goes here
}
}


Where the modifier can be private, public, protected or internal. The return type can be any valid C# types. The 'this' is a special keyword in C# to indicate the object of the current class. The formal-argument-list specifies the parameters of the indexer. The formal parameter list of an indexer corresponds to that of a method, except that at least one parameter must be specified, and that the ref and out parameter modifiers are not permitted. Remember that indexers in C# must have at least one parameter. Other wise the compiler will generate a compilation error.

Example:

// C#: INDEXER
using System;
using System.Collections;
class MyClass
{
private string []data = new string[5];
public string this [int index]
{
get
{
return data[index];
}
set
{
data[index] = value;
}
}
}
class MyClient
{
public static void Main()
{
MyClass mc = new MyClass();
mc[0] = "Hello";
mc[1] = "A3-126";
mc[2] = "Google";
mc[3] = "Irla";
mc[4] = "Mumbai";
Console.WriteLine("{0},{1},{2},{3},{4}",mc[0],mc[1],mc[2],mc[3],mc[4]);
}
}


The indexers in C# can be overloaded just like member functions. The formal parameter list of an indexer defines the signature of the indexer. Specifically, the signature of an indexer consists of the number and types of its formal parameters. The element type is not part of an indexer's signature, nor is the names of the formal parameters. The signature of an indexer must differ from the signatures of all other indexers declared in the same class. C# do not have the concept of static indexers. If we declare an indexer static, the compiler will show a compilation time error.

Indexers & Inheritance

Just like any other class members, indexers can also participate in inheritance. A base class indexer is inherited to the derived class.

//C#: Indexer : Inheritance
using System;
class Base
{
public int this[int indxer]
{
get
{
Console.Write("Base GET");
return 10;
}
set
{
Console.Write("Base SET");
}
}
}
class Derived : Base
{

}
class MyClient
{
public static void Main()
{
Derived d1 = new Derived();
d1[0] = 10;
Console.WriteLine(d1[0]);//Displays 'Base SET Base GET 10'
}
}


Indexers & Polymorphism

A Base class indexer can be polymorphicaly overridden in a Derived class. But remember that the modifiers like virtual, override etc are using at property level, not at accessor level.

//C#: Indexer : Polymorphism
using System;
class Base
{
public virtual int this[int index]
{
get
{
Console.Write("Base GET");
return 10;
}
set
{
Console.Write("Base SET");
}
}
}
class Derived : Base
{
public override int this[int index]
{
get
{
Console.Write("Derived GET");
return 10;
}
set
{
Console.Write("Derived SET");
}
}
}
class MyClient
{
public static void Main()
{
Base b1 = new Derived();
b1[0]= 10;
Console.WriteLine(b1[0]);//Displays 'Derived SET Derived GET 10'
}
}

Abstract Indexers

An indexer inside a class can be declared as abstract by using the keyword abstract. Remember that an abstract indexer in a class carries no code at all. The get/set accessors are simply represented with a semicolon. In the derived class we must implement both set and get assessors.

If the abstract class contains only set accessor, we can implement only set in the derived class.
The following program shows an abstract indexer in action.

//C#: Indexer : Abstract
using System;
abstract class Abstract
{
public abstract int this[int index]
{
get;
set;
}
}
class Concrete : Abstract
{
public override int this[int index]
{
get
{
Console.Write(" GET");
return 10;
}
set
{
Console.Write(" SET");
}
}
}
class MyClient
{
public static void Main()
{
Concrete c1 = new Concrete();
c1[0] = 10;
Console.WriteLine(c1[0]);//Displays 'SET GET 10'
}
}

Indexers & Properties

1. An index is identified by it's signature. But a property is identified it's name.
2. An indexer is always an instance member, but a property can be static also.
3. An indexer is accessed through an element access. But a property is through a member access.

Attributes and Reflection in C#

Attributes provide a powerful way to extend metadata by associating declarative information with C# code. The attribute information is stored with the metadata of the element and can be easily retrieved at runtime using reflection.

Attribute
An attribute is essentially an object that represents the data that is associated with a program element. The element to which an attribute is attached is referred to as the target of that attribute.
Attribute targets can be one of the following:

  • All
  • Assembly
  • Class
  • Constructor
  • Delegate
  • Enum
  • Event
  • Field
  • Interface
  • Method
  • Module
  • Parameter
  • Property
  • ReturnValue
  • Struct

Types of Attributes

Attributes are basically of two types: intrinsic and custom.

Intrinsic Attributes
Intrinsic attributes are supplied as part of the Common Language Runtime, and they are integrated into .NET.

In this example below we use a pre–defined attribute, Obsolete, which marks a program entity as obsolete. The attribute accepts two parameters of which the first is a message and the second a boolean value. If the second parameter is true, the compiler gives an error if the method is invoked, and a warning otherwise

Example: Using the Obsolete Attribute

using System;
public class Test
{
[Obsolete("This method is deprecated. Usethe method Display(string)
instead.", false)]
void Display()
{
}
void Display(string s)
{
}
public static void Main( )
{
Test test = new Test ();
test.Display ();
}
}

Custom Attributes:

Custom attributes are attributes that we create for our own purposes. Attributes are public classes and are initialized using constructors. Every attribute must have at least one constructor. The constructors can be overloaded to allow the attribute to be applied to the class in multiple ways.

To create a custom attribute, we have to derive our new custom Attribute class from the class System.Attribute, as shown below.

Example: Declaring a Custom Attribute Class

using System;
public class Comments : Attribute
{
}

Next, we have to specify the target of the attribute using the AttributeUsage attribute. An attribute is applied to the target by specifying the attribute name in brackets as shown in the example below.

Example: Declaring the Custom Attribute Class

public class Comments : System.Attribute[AttributeUsage(AttributeTargets.Class
AttributeTargets.Constructor
AttributeTargets.Field
AttributeTargets.Method
AttributeTargets.Property,
AllowMultiple = true)]
AttributeUsage

The scope and target of the attribute can be defined by applying AttributeUsage. It contains three properties, which we can set to specify attributes.

AllowOn
This is a set of flags that indicates the program entities on which the attribute can be placed. Multiple AttributeTargets can also be specified using a bitwise OR operator.

AllowMultiple
AllowMultiple lets you specify whether you can apply multiple instances of a particular attribute to the same element. If AllowMultiple is set to true, then inherited classes will inherit all instances of the attribute from the parent class. The default value for AllowMultiple is false.

Inherited
The Inherited property determines whether the attribute will be inherited by classes that are derived from the classes to which the attribute is applied. The default value for Inherited is true, indicating that an attribute applied to the base class will be applied to all its derived classes.

Attribute Parameters
Attributes accept parameters for customization. They take two types of parameters, positional and named.

Positional Parameters
Positional parameters are specified using constructor arguments to the attribute class.

Named Parameters
Named parameters are defined by having a non-static field or property in the attribute class.

Attribute parameter types can be:
bool, byte, char, double, float, int, long, short, string
System.object
System.Type
A public enum
A one-dimensional array of the above types

Implementing a Custom Attribute class

The following section shows a custom attribute class called Comments, the application of the attribute to several entities of a class called Employee, and usage of reflection on this class to retrieve the attributes already specified. In the Comments class, the parameters author, type, and description are compulsory positional parameters and status is an optional named parameter.

Example: Implementing the Custom Attribute Class

using System;
using System.Reflection;
[AttributeUsage( AttributeTargets.All )]
public class Comments : System.Attribute
{
public string author = String.Empty;
public string type = String.Empty;
public string description = String.Empty;
private string status = String.Empty;
public Comments(string author, string type,string description)
{
this.author = author;
this.type = type;
this.description = description;
}
public string Status
{
get
{
return status;
}
set
{
status = value;
}
}
public static void DisplayAttributes(Type t)
{
Comments comments = (Comments) Attribute.GetCustomAttribute(t,typeof
(Comments));
Console.WriteLine("The Author is:{0}." , comments.author);
Console.WriteLine("The Description is:{0}." , comments.description);
System.Console.WriteLine("Class Name:{0}", t.Name);
MethodInfo[] methods = t.GetMethods();
object[] attributes = null;
for (int i = 0, l = methods.GetLength(0); i< mi =" methods[i];" attributes =" mi.GetCustomAttributes(true);" thecomments =" (Comments)attribute;" status = "Complete" employeename =" value;" status = "Complete" basic =" value;" status = "Complete" employee =" new">

Reflection

Reflection provides objects that encapsulate assemblies, modules, and types. It is the process by which a program can inspect metadata information dynamically using the reflection API. Using reflection, we can create instances of a type, bind the type to an existing object, or get the type from an existing object and invoke its methods or access its fields and properties. Reflection is much the same as RTTI of native C++ but with a major difference in that reflection in C# works with managed code and is much more powerful.

The reflection classes are contained in the namespace System.Reflection. The classes in the Reflection namespace, along with the System.Type and System.TypedReference classes, provide support for examining and interacting with the metadata. The abstract base class Type helps access metadata information. The types include the constructors, methods, fields, properties, and events of a class and the module and the assembly in which these are stored.

The System.Reflection namespace defines the following types:

  • Assembly
  • Module
  • Enum
  • MethodInfo
  • ConstructorInfo
  • MemberInfo
  • ParameterInfo
  • Type
  • FieldInfo
  • EventInfo
  • PropertyInfo

Here is a complete example of a class that inspects another class and demonstrates the power of reflection to display the metadata information dynamically.

Example: Reflection in Action

using System;
using System.Reflection;
namespace ReflectionTest
{
public class Employee
{
string name;
public string Name
{
get
{
return name ;
}
set
{
name = value ;
}
}
public Employee()
{
}
public Employee ( string name )
{
this.name = name;
}
public void Display ()
{
}
}
public class Reflect
{
public static void DisplayDetails(Type type)
{
Console.WriteLine ( "Class: " + type) ;
Console.WriteLine ();
Console.WriteLine ( "Namespace: " +type.Namespace ) ;
Console.WriteLine ();
ConstructorInfo[] constructorInfo =
type.GetConstructors( );
Console.WriteLine( "Constructors:--") ;
foreach( ConstructorInfo c in constructorInfo)
{
Console.WriteLine( c ) ;
}

PropertyInfo[] propertyInfo =type.GetProperties( );
Console.WriteLine ();
Console.WriteLine( "Properties:--" );
foreach( PropertyInfo p in propertyInfo )
{
Console.WriteLine( p ) ;
}
MethodInfo[] methodInfo = type.GetMethods( ) ;
Console.WriteLine ();
Console.WriteLine( "Methods:--" ) ;
ParameterInfo[] parameterInfo = null;
foreach( MethodInfo m in methodInfo )
{
Console.WriteLine( "Method Name: "+ m.Name ) ;
parameterInfo = m.GetParameters () ;
foreach ( ParameterInfo p in parameterInfo )
{
Console.WriteLine("Parameter Type:" + p.ParameterType + " Parameter
Name: " + p.Name ) ;
}
}
}
public static void Main ( string[] args )
{
DisplayDetails(typeof(Employee));
}
}
}

Reflection in C#

Reflection:
Reflection is one of the features of .Net Framework and has greater importance during the development of large applications. In brief it is a powerful way of collecting and manipulate information present in application's assemblies and its metadata. Metadata contain all the Type information used by the application. The ability to obtain information at runtime also makes it even more advantageous. When reflection is used along with system type, it allows the developer to get the valuable information about all the types and about the assemblies. We can even create the instances and then invoke various types that are used across the application.

What is Reflection?
Reflection is the ability to find out information about objects, the application details (assemblies), its metadata at run-time.

This allows application to collect information about itself and also manipulate on itself. It can be used effectively to find all the types in an assembly and/or dynamically invoke methods in an assembly. This includes information about the type, properties, methods and events of an object and to invoke the methods of object Invoke method can be used too. With reflection we can dynamically create an instance of a type, bind the type to an existing object, or get the type from an existing object and invoke its methods or access its fields and properties. If Attributes (C#) are used in application, then with help of reflection we can access these attributes. It can be even used to emit Intermediate Language code dynamically so that the generated code can be executed directly.

How to use Reflection in our applications?
System.Reflection namespace contains all the Reflection related classes. These classes are used to get information from any of the class under .NET framework. The Type class is the root of all reflection operations. Type is an abstract base class that acts as means to access metadata though the reflection classes. Using Type object, any information related to methods, implementation details and manipulating information can be obtained. The types include the constructors, methods, fields, properties, and events of a class, along with this the module and the assembly in which these information are present can be accessed and manipulated easily.
As mentioned earlier, we can use reflection to dynamically create an instance of any type, bind the type to an existing object, or get the type from an existing object. Once this is done appropriate method can be invoked, access the fields and properties. This can be done by specifying the Type of object or by specifying both assembly and Type of the object that needs to be created. By this the new object created acts like any other object and associated methods, fields and properties can be easily accessed. With reflection we can also find out about various methods associated with newly created object and how to use these object. To find out the attributes and methods associated with an object we can use the abstract class MemberInfo, this class is available under the namespace System.Reflection.
Reflection can be used in following different ways to get different information about various Types.

All the below mentioned classes are available under the namespace System.Reflection.

Assembly Class can be used to get the information and manipulate the assembly. This class allows us to define and load assemblies, load modules that are listed in the assembly manifest, and locate a type from this assembly and create an instance of it.
Assembly.GetType or Assembly.GetTypes are the two methods that can be used to get the Type object from assemblies that have not been loaded. To these method name of the Type(s) is passed as the parameter. Type.GetType is used similarly as mentioned above only distinction is that here the assemblies are loaded.
Example: The following statement fetches mscorlib assembly information

Assembly assemblyInformation = typeof(Object).Module.Assembly;

// Loads an assembly using its file name
Assembly assemblyInformation = Assembly.LoadFrom("MyApplicationToRu n.exe");

// Fetch the types available in the assembly
Type [] assemblyTypeInformation = assemblyInformation.GetTypes ();

foreach (Type TypeInformation in assemblyTypeInformation)
{
Console.WriteLine (TypeInformation.FullName);
}

As shown above once the Type is obtained, there are many ways you can fetch the information about the members of that type. For example, to find out about all the type's members we can use the Type.GetMembers method, which obtains an array of MemberInfo objects describing each of the members of the current type.
Module Class is used for the reflection of the module. This class is used to get information about parent assembly, classes in the module, all the global methods available in the classes.
ConstructorInfo Class is used for the reflection of a constructor, and used to fetch the information about constructor also constructor can be invoked. Constructor information like name, parameters, access modifiers, and various implementation details (such as abstract or virtual) can be obtained. Class Objects are created when constructor of a ConstructorInfo is invoked this returns either the GetConstructors or GetConstructor method of a Type object.
MethodInfo Class is used to obtain information such as the name, return type, parameters, access modifiers (such as public or private), and implementation details (such as ab,stract or virtual) of a any method inside the class, module, assembly. GetMethods or GetMethod method of a Type are used to on the to obtain the information.
FieldInfo Class, as the name suggest this class is used to get the information such as the name, access modifiers (such as public or private) and implementation details (such as static) of a field. Even to get or set field values of a class.

EventInfo Class is used to fetch the information about name, event-handler data type, custom attributes, declaring type, and reflected type of an event. This class is also used to add or remove event handlers.

PropertyInfo Class is used to fetch the information about the name, data type, declaring type, reflected type, and read-only or writable status of a property. Also we can get or set property values using this class.

ParameterInfo Class is used to fetch the information about parameter's name, data type, whether a parameter is an input or output parameter, and the position of the parameter in a method signature. We can GetParameters method in this class that returns an array of ParameterInfo objects representing the parameters of a method, in order.
Another important namespace is System.Reflection.Emit Namespace. This name space can be used to create the type at run time and invoke as and when required. Basic usage of this namespace is to write the information to appropriate types. System.Reflection.Emit namespace contains classes that can be used by the compiler or tool to emit metadata and Microsoft intermediate language (MSIL). The compiler or script generators basically use this information.

Wednesday, May 30, 2007

Reading and Writing Text Files - C#

// File IO using class StreamWriter

using System;
using System.IO; // TextWriter, StreamWriter

public class MyClass
{
public static void Main()
{
string text;

text = "A quick brown fox\n";
text += "jumps over a \n";
text += "little lazzy dog.\n";

// create a writer and open the file
TextWriter tw = new StreamWriter("typing.txt");

// write a line of text (present date/time) to the file
tw.WriteLine(DateTime.Now);

// write the rest of the text lines
tw.Write(text);

// close the stream
tw.Close();

// read the text file back ...
// create reader & open file
TextReader tr = new StreamReader("typing.txt");

// read first line of text (here date/time)
Console.WriteLine(tr.ReadLine());

// read the text, next 2 lines
Console.WriteLine(tr.ReadLine());
Console.WriteLine(tr.ReadLine());

// read the rest of the text lines
Console.WriteLine(tr.ReadToEnd());

// close the stream
tr.Close();

// wait to look at console display
Console.Write("\nPress Enter to exit ...");
Console.Read();

}
}

Monday, May 28, 2007

Disable/Enable ListItems - ASP.NET

Introduction

1. Add a CheckBoxList to your ASP.NET WebForm and give it an ID of checkBoxListTest.
2. Add a call to the LoadCheckBoxList in the Page_Load event.
3. Add the LoadCheckBoxList method to your webpage class.
4. Add the JavaScript function inside the head of the HTML.

ASP.NET CodeBehind

private void Page_Load(object sender, System.EventArgs e)
{
if(!this.IsPostBack)
{
LoadCheckBoxList();
}
}

private void LoadCheckBoxList()
{
this.checkBoxListTest.Attributes.Add("onclick",
"disableListItems('checkBoxListTest', '2', '3')");

// Add three items to the CheckBoxList.
for(int i=0; i < item =" new">

This method adds the onclick function disableListItems to the CheckBoxList attributes collection. The function will disable all the items except for the last item in the list when it is checked. The method also adds three items to the CheckBoxList.

JavaScript Function

function disableListItems(checkBoxListId, checkBoxIndex, numOfItems)
{
// Get the checkboxlist object.
objCtrl = document.getElementById(checkBoxListId);

// Does the checkboxlist not exist?
if(objCtrl == null)
{
return;
}

var i = 0;
var objItem = null;
// Get the checkbox to verify.
var objItemChecked =
document.getElementById(checkBoxListId + '_' + checkBoxIndex);

// Does the individual checkbox exist?
if(objItemChecked == null)
{
return;
}

// Is the checkbox to verify checked?
var isChecked = objItemChecked.checked;

// Loop through the checkboxes in the list.
for(i = 0; i < numOfItems; i++)
{
objItem = document.getElementById(checkBoxListId + '_' + i);

if(objItem == null)
{
continue;
}

// If i does not equal the checkbox that is never to be disabled.
if(i != checkBoxIndex)
{
// Disable/Enable the checkbox.
objItem.disabled = isChecked;
// Should the checkbox be disabled?
if(isChecked)
{
// Uncheck the checkbox.
objItem.checked = false;
}
}
}
}


The above code is the JavaScript function that is invoked by the onclick event of the CheckBoxList.

Sunday, May 27, 2007

Binding DataGridView, GridView with SQL statement

Introduction
How to populate DataGridView, GridView with SQL statement in C#

When we do the development, we always want to make the code simple and error free if possible. In C#, GridView for web based application and DataGridView for windows form based application are different in using and behavior. It looks like Microsoft has two different teams to develop GridView and DataGridView separately. This is why I wrote this article to share the coding for each control. Here I am using MS Visual Studio 2005.


I. Populate GridView control for web based application with SQL statement

Let us put GridView1 control on the web form from Toolbox. The coding is straight forward and is like the following:

protected void Page_Load(object sender, EventArgs e)
{
string strSQLconnection = "Data Source=dbServer;Initial Catalog=testDB;Integrated Security=True";
SqlConnection sqlConnection = new SqlConnection(strSQLconnection);
SqlCommand sqlCommand = new SqlCommand("select * from table1", sqlConnection);
sqlConnection.Open();
SqlDataReader reader = sqlCommand.ExecuteReader();
GridView1.DataSource = reader;
GridView1.DataBind();
}

You run the code and you can see the result. But when you see the data binding for DataGridView in the following section, it is quite different.

II. Populate DataGridView control with SQL statement for Window form based application

When I used the DataGridView control in C# in MS Visual Studio 2005, I found DataGridView control is not friendly to use. Windows form-based DataGridView control is different from web based GridView control. DataGridView doesn’t have DataBind() method. It took me a few days to figure out.

The logic is like this :

Create data set from SQL statement or stored procedure
Create a table to hold this data set
Create a BindingSource and bind this table with this BindingSource
Then bind this BindingSource with GridView control.

This looks trivial. But I found it is very efficient and error free.

Let us put DataGridView control and BindingSource control on the windows form from Toolbox. Let us name DataGridView control as dbGridView, BindingSource control as dbBindSource. Let us apply the following code:

private void Form1_Load(object sender, EventArgs e)
{
string strCon = "Data Source=dbServer;Initial Catalog=testDB;Integrated Security=True";
string strSQL = “select * from table1”;
SqlDataAdapter dataAdapter = new SqlDataAdapter(strSQL, strCon);
SqlCommandBuilder commandBuilder = new SqlCommandBuilder(dataAdapter);
// Populate a new data table and bind it to the BindingSource.
DataTable table = new DataTable();
table.Locale = System.Globalization.CultureInfo.InvariantCulture;
dataAdapter.Fill(table);
dbBindSource.DataSource = table;
// Resize the DataGridView columns to fit the newly loaded content.
dbGridView.AutoResizeColumns(DataGridViewAutoSizeColumnsMode.AllCellsExceptHeader);
// you can make it grid readonly.
dbGridView.ReadOnly = true;
// finally bind the data to the grid
dbGridView.DataSource = dbBindSource;
}


Now we compile it and run it. You can see the data in the grid.

Datagrid - Editing, Updating, Cancel, Selecting Rows

Datagrid - Editing, Updating, Cancel, Selecting Rows

Introduction:
Microsoft.net framework ships with many usefull controls. These controls makes the life of developer easy by providing them with the functinality they want.
Among those many controls is the DataGrid control which helps the developer to display the data on the screen in the format of an arranged table. Datagrid is one of the 3 templated controls provided by the Microsoft.net framework. The other two are DataList and the Repeator control. Many new controls are being developed everyday but their basic idea is inherited from the classic DataGrid control.
In this article we will see the most common use of the datagrid control. Lets set up out datagrid.

Setting up the Datagrid:

Lets first set up our datagrid.
1. Drag and Drop the datagrid control from your toolbox to the webform.
2. The datagrid will appear as a simple table.
3. You can make the datagrid pretty by selecting the Auto format features.
Okay your datagrid is set up, lets add some columns.
Adding the Bound Columns:
Adding the bound colums in the datagrid is pretty simple.
1. Right click on the datagrid and select Property Builder.
2. Click on the Columns tab and uncheck "Generate columns automatically".
3. Add three bound columns, give the columns some name in the column name field. And finally add the edit,update,cancel buttons which can be found under the button option.
Note: Please also note that the button type should be link button or else it wont work.

Storing the database connection:
In this demo I am storing the database connection in the Web.config file. The database name is DBSnippets, which has one table known as tblPerson. Here is the web.config file.

Okay till now we have made the Datagrid and also saved the connection string in the web.config file. Now the time has come to code and handle the events.
Lets first make the BindData method which will retrieve the contents from the database and bind it on the screen. This will be one of the most important methods since it will be called whenever the page is loaded for the first time.

private void Page_Load(object sender, System.EventArgs e)
{
if(!Page.IsPostBack)
{
BindData();
}
}


As you see the BindData method is called when the page is not posted back. Now lets see the BindData method in details.

public void BindData()
{
SqlCommand myCommand = new SqlCommand("SP_SELECT_PERSONS",myConnection);
myCommand.CommandType = CommandType.StoredProcedure;
SqlDataAdapter myAdapter = new SqlDataAdapter(myCommand);
DataSet ds = new DataSet();
myAdapter.Fill(ds,"tblPerson");
myConnection.Open();
myCommand.ExecuteNonQuery();
myDataGrid.DataSource = ds;
myDataGrid.DataBind();
myConnection.Close();
}


Explanation of the BindData method:
1. First we make a SqlCommand object and named it myCommand. The SqlCommand object takes a stored procedure as an input and the SqlConnection.
2. We feed the command object to the DataAdapter object named as myAdapter.
3. A dataset is declared which is filled with the result of the Stored procedure.
4. myDataGrid.DataBind() binds the datagrid to the page. Don't forget to bind the grid or else it won't be displayed.
5. Later we opened the connection and execute the query.
Now Lets see the stored procedure.

Stored Procedure:

CREATE PROCEDURE SP_SELECT_PERSONS
AS
SELECT * FROM tblPerson GO

As you can see that the above Stored Procedure is pretty simple. All we are doing is we are just selected all the columns from the table person.
Lets now make the Edit method which will display textboxes inside the datagrid so that a user can insert data. This sort of editing is also known as Inline editing.
Making datagrid editable is pretty simple. All you to do is to code few lines in the EditCommand event of the datagrid. You can view all the events supported by DataGrid by selecting properties and than selecting the Thunder/Flash yellow sign at the top of the properties window.

Lets call our Edit DataGrid event Edit_DataGrid.

private void Edit_DataGrid(object source, System.Web.UI.WebControls.DataGridCommandEventArgs e)
{
// We use CommandEventArgs e to get the row which is being clicked
// This also changes the DataGrid labels into Textboxes so user can edit them
myDataGrid.EditItemIndex = e.Item.ItemIndex;
// Always bind the data so the datagrid can be displayed.
BindData();
}


When the Edit link button is clicked your DataGrid will look something like this:

As you see when you click the edit link the update and the cancel link button automatically appears.
Lets now see the code for the Cancel Event. Cancel event is used when you are in the edit mode and you change your mind about not to edit. So you click the cancel link button and the Datagrid returns back to its orginal condition.

private void Cancel_DataGrid(object source, System.Web.UI.WebControls.DataGridCommandEventArgs e)
{
// All we do in the cancel method is to assign '-1' to the datagrid editItemIndex
// Once the edititemindex is set to '-1' the datagrid returns back to its original condition
myDataGrid.EditItemIndex = -1;
BindData();
}

Okay now we come to a slightly difficult step. We will carefully look at the Update method and see how it works.

private void Update_DataGrid(object source, System.Web.UI.WebControls.DataGridCommandEventArgs e)
{
System.Web.UI.WebControls.TextBox cName = new System.Web.UI.WebControls.TextBox();
cName = (System.Web.UI.WebControls.TextBox) e.Item.Cells[1].Controls[0];
SqlCommand myCommand = new SqlCommand("SP_UpdatePerson",myConnection);
myCommand.CommandType = CommandType.StoredProcedure;
myCommand.Parameters.Add(new SqlParameter("@PersonName",SqlDbType.NVarChar,50));
myCommand.Parameters["@PersonName"].Value = cName.Text;
myConnection.Open();
myCommand.ExecuteNonQuery();
myConnection.Close();
myDataGrid.EditItemIndex = -1;
BindData();
}

Lets now dig into this method and see whats going on.
• The name of the method as you can see is Update_DataGrid, this event is fired when you click the update link button which appears after clicking the edit button.
• We declare a variable of TextBox type and call it cName. The reason of declaring a TextBox is that the value that we want is inside the TextBox which is inside the DataGrid control.
• Later we made the SqlCommand object which takes stored procedure "SP_UpdatePerson", which will be discussed afterwords.
• After marking the command object with the stored procedure we passed the parameter which is PersonName.
• Finally we execute the Query and set the editItemIndex property of the DataGrid '-1' which will bring the datagrid back to its original form i.e without any textboxes.
• Don't forget to bind the datagrid.

Update Stored Procedure:

CREATE PROCEDURE SP_UpdatePerson
@PersonName nvarchar(50)
AS
UPDATE tblPerson SET PersonName = @PersonName WHERE PersonName = @PersonName;

Selecting Item from the Datagrid:

Another cool feature of the Datagrid control is that you can select any row from the datagrid and it will be displayed as the highligted row in the grid.
The highlight row event is called SelectedIndexChanged event. The event is called when the select column is clicked. The select column can be added to the datagrid using the property builder, just like we added "edit/cancel/update" link buttons.

// This event is fired when the Select is clicked
private void Select_DataGrid(object sender, System.EventArgs e)
{
// prints the value of the first cell in the DataGrid
Label2.Text += myDataGrid.SelectedItem.Cells[0].Text;
}

This method is pretty simple. When the datagrid select link button is pressed. We retrieve the item from the datagrid which is residing on the same row on which the link button is pressed. As we can see above in the code that we are retrieving the value from the first column of the datagrid.