Menus

Friday, January 6, 2012

Introduction to Model View Control (MVC) Pattern using C#


The benefits of using the Model-View-Control (MVC) pattern in our development projects is that we can completely decouple our business and presentation application layers. Furthermore, we will have a completely independent object to control the presentation layer. The independence between the objects/layers in our project that the MVC provides will make maintenance somewhat easier and code reuse very easy (as you'll see below).

As a general practice we know we want to keep the object dependencies in our projects to a minimum so changes are easy and we can reuse the code we've worked so hard on. To accomplish this we will follow a general principle of "programming to the interface, not the class" using the MVC pattern.

Our mission, if we choose to accept it...
We have been commissioned to build a ACME 2000 Sports Car business object and our task is to create a simple windows interface to (1) display the vehicle's current direction and speed, and (2) enable the end user to change direction, accelerate, and decelerate.  And of course, there will be scope creep.

There are already rumors at ACME that if our project is successful, we will eventually a need to develop a similar interface for the ACME 2 Pickup Truck and the ACME 1 Tricycle. As developers, we also know that the ACME management team will eventually say "Hey, this is really cool. Can we see it on the company's intranet?" All of this in mind, we want to deliver a product that will be easily scalable so we can be sure to have food on our plates for some time.

So, coincidentally, we think... "This is a perfect situation to use the MVC!!".

Our Architecture Overview
Ok, now we know that we want to use the MVC, we need to figure out what the heck it is. Through our research we come up with the three parts of the MVC: The Model, Control, and View. In our system, the Model would be our car, the View would be the user interface, and the Control is what ties the two together.

Model-View-Control Overview

To make any changes to the Model (our ACME 2000 sports car), we'll be using our Control. Our Control will make the request to the Model (our ACME 2000 sports car), and update our View, which is our user interface (UI).

This seems simple enough, but here's the first problem we have to solve: What happens when the end user wants to make a change to our ACME 2000 sports car, such as going faster or turning? They are going to have to do it by requesting a change using the Control, through the View (our windows form).

Model-View-Control Model

Now we are left with one last problem to solve. What if the View doesn't have the necessary information to display the current state of the Model?  We're going to have to add one more arrow to our diagram: The View will be able to request the Model's state in order to get what it needs to display the information about the state of the Model.

Model View Control View
 

Finally, our end user (our driver) will be interacting with our entire ACME Vehicle Control system through the View.  If they want to request a change to the system, such as adding a bit of acceleration, the request will be initiated from the View and handled by the Control. 

The Control will then ask the Model to change and make any necessary changes to the View. For example if the ACME 2000 Sports Car has a "floor it" request from an unruly driver and is now traveling to fast to make a turn, the Control will know to disable the ability to turn in the View, thus preventing a catastrophic pileup in the middle of rush-hour (whew!).

The Model (the ACME 2000 Sports Car) will notify the View that it's speed has increased and the View will update where appropriate.

So after all that, here's the overview of what we will be building:

Model View Control View

Getting Started: Parts... Parts... Parts...
Being developers who always think ahead, we want to be sure our system will have a long and prosperous life. This means being prepared for as many changes at ACME as possible. In order to do this we know to follow two golden rules... "keep your classes loosely coupled" and, in order to accomplish this... "program to the interface".

So we will make three interfaces (as you may have guessed, one for the Model, one for the View, and one for the Control).

After much research and laborious interviews with the folks at ACME, we find out more about the system specifications. We want to be sure that we can set the maximum speeds for traveling forward, backwards ,and turning. We also need to be able to speed up, slow down, and turn left and right. Our "dashboard" view must display the current speed and direction.

It's a tall order to implement all of these requirements, but we're sure we can handle it...

First, let's take care of some preliminary items.  We'll need something to represent the direction and turn requests.  We'll create two enumerables, AbsoluteDirection and RelativeDirection.



public enum AbsoluteDirection
{
North=0, East, South, West
}

public enum RelativeDirection
{
Right, Left, Back
}

Next, let's tackle the Control interface. We know the Control has to pass requests to the Model, specifically: Accelerate, Decelerate, and Turn. We'll create an IVehicleControl interface with the appropriate methods.

public interface IVehicleControl
{
void Accelerate(int paramAmount);
void Decelerate(int paramAmount);
void Turn(RelativeDirection paramDirection);
}

Now we'll put together the Model interface.  We need to know the Vehicle's name, speed, maximum speed, maximum reverse speed, maximum turn speed and direction. We also need the methods to accelerate, decelerate, and turn.



public interface IVehicleModel
{
string Name{ get; set;}
int Speed{ get; set;}
int MaxSpeed{ get;}
int MaxTurnSpeed{ get;}
int MaxReverseSpeed { get;}
AbsoluteDirection Direction{get; set;}
void Turn(RelativeDirection paramDirection);
void Accelerate(int paramAmount);
void Decelerate(int paramAmount);
}


And Finally, we'll put together the View interface. We know the view should expose some functionality to the Control, such as enabling and disabling acceleration, deceleration, and turn requests.


public class IVehicleView
{
void DisableAcceleration();
void EnableAcceleration();
void DisableDeceleration();
void EnableDeceleration();
void DisableTurning();
void EnableTurning();
}



Now we have to make a few tweaks to our interfaces to allow them to interact. First of all, any Control should be aware of it's View and Model, so we'll add "SetModel" and "SetView" methods to our IvehicleControl interface:

public interface IVehicleControl
{
void RequestAccelerate(int paramAmount);
void RequestDecelerate(int paramAmount);
void RequestTurn(RelativeDirection paramDirection);
void SetModel(IVehicleModel paramAuto);
void SetView(IVehicleView paramView);
}


The next part is a bit tricky. We want the View to be aware of changes in the Model. To do this we'll use a GOF design pattern "Observer".

To implement the Observer pattern, we need to add the following methods to the Model (which will be "observed" by the View): AddObserver, RemoveObserver, and NotifyObservers.



public interface IVehicleModel
{
string Name{ get; set;}
int Speed{ get; set;}
int MaxSpeed{ get;}
int MaxTurnSpeed{ get;}
int MaxReverseSpeed { get;}
AbsoluteDirection Direction{get; set;}
void Turn(RelativeDirection paramDirection);
void Accelerate(int paramAmount);
void Decelerate(int paramAmount);
void AddObserver(IVehicleView paramView);
void RemoveObserver(IVehicleView paramView);
void NotifyObservers();
}



...and add the following method to the View (which will be "observing" the Model). What will happen is the Model will have a reference to the View. When the Model changes, it will call the NotifyObservers() method and pass a reference to itself and notify the View of a change by calling the Update() method of the View. (It will become clear as mud when we wire everything up later).

public class IVehicleView
{
void DisableAcceleration();
void EnableAcceleration();
void DisableDeceleration();
void EnableDeceleration();
void DisableTurning();
void EnableTurning();
void Update(IVehicleModel paramModel);
}


So now we have our interfaces put together. We are only going to use references to these interfaces in the rest of our code to ensure we have loose coupling (which we know is a good thing). Any user interface that shows the state of a Vehicle will implement IVehicleView, all of our ACME automobiles will implement IVehicleModel, and we'll make controls for our ACME automobiles with ACME vehicle controls which will implement IVehicleControl.

Next... What things will have things in common?
We know all our vehicles should act the same, so we're going to create a common code base "skeleton" to handle their operation. This is going to be an abstract class because we don't want anyone driving around a skeleton (you can't make an instance of an abstract class). We'll call it Automobile. We'll use an ArrayList (from System.Collections) to keep track of all the interested Views (remember the Observer pattern?). We could have used a plain old array of IVehicleView references, but we're all getting fatigued at this point and want to get through this article. If you're interested, check out the implementation of the AddObserver, RemoveObserver, and NotifyObservers methods to get an idea of how the Observer pattern works by helping our IVehicleModel interact with the IVehicleView. Every time there is a change in speed or direction, the Automobile notifies all IVehicleViews



public abstract class Automobile: IVehicleModel
{
#region "Declarations "
private ArrayList aList = new ArrayList();
private int mintSpeed = 0;
private int mintMaxSpeed = 0;
private int mintMaxTurnSpeed = 0;
private int mintMaxReverseSpeed = 0;
private AbsoluteDirection mDirection = AbsoluteDirection.North;
private string mstrName = "";
#endregion
#region
"Constructor"
public Automobile(int paramMaxSpeed, int paramMaxTurnSpeed, int paramMaxReverseSpeed, string paramName)
{
this.mintMaxSpeed = paramMaxSpeed;
this.mintMaxTurnSpeed = paramMaxTurnSpeed;
this.mintMaxReverseSpeed = paramMaxReverseSpeed;
this.mstrName = paramName;
}
#endregion
#region
"IVehicleModel Members"
public void AddObserver(IVehicleView paramView)
{
aList.Add(paramView);
}
public void RemoveObserver(IVehicleView paramView)
{
aList.Remove(paramView);
}
public void NotifyObservers()
{
foreach(IVehicleView view in aList)
{
view.Update(this);
}
}
public string Name
{
get{
return this.mstrName;
}
set{
this.mstrName = value;
}
}
public int Speed
{
get{
return this.mintSpeed;
}
}
public int MaxSpeed
{
get{
return this.mintMaxSpeed;
}
}
public int MaxTurnSpeed
{
get{
return this.mintMaxTurnSpeed;
}
}
public int MaxReverseSpeed
{
get{
return this.mintMaxReverseSpeed;
}
}
public AbsoluteDirection Direction
{
get{
return this.mDirection;
}
}
public void Turn(RelativeDirection paramDirection)
{
AbsoluteDirection newDirection;
switch(paramDirection)
{
case RelativeDirection.Right:
newDirection = (AbsoluteDirection)((int)(this.mDirection + 1) %4);
break;
case RelativeDirection.Left:
newDirection = (AbsoluteDirection)((int)(this.mDirection + 3) %4);
break;
case RelativeDirection.Back:
newDirection = (AbsoluteDirection)((int)(this.mDirection + 2) %4);
break;
default:
newDirection = AbsoluteDirection.North;
break;
}
this.mDirection = newDirection;
this.NotifyObservers();
}
public void Accelerate(int paramAmount)
{
this.mintSpeed += paramAmount;
if(mintSpeed >= this.mintMaxSpeed) mintSpeed = mintMaxSpeed;
this.NotifyObservers();
}
public void Decelerate(int paramAmount)
{
this.mintSpeed -= paramAmount;
if(mintSpeed <= this.mintMaxReverseSpeed) mintSpeed = mintMaxReverseSpeed;
this.NotifyObservers();
}
#endregion}



Last but not least...
Now that our "ACME Framework" is in place, we just have to set up our concrete classes and our interface. Let's take care of the last two class first which will be our Control and our Model...

Here's our concrete AutomobileControl which implements the IVehicleControl interface. Our AutomobileControl will also set the View depending on the state of the Model (check out the SetView method which is called every time there is a request passed to the Model).

Notice, we just have references to the IVehicleModel (not the Automobile abstract class) to keep things loose and IVehicleView (not a specific View).



public class AutomobileControl: IVehicleControl
{
private IVehicleModel Model;private IVehicleView View;public AutomobileControl(IVehicleModel paramModel, IVehicleView paramView)
{
this.Model = paramModel;this.View = paramView;
}
public AutomobileControl()
{
}
#region IVehicleControl Memberspublic void SetModel(IVehicleModel paramModel)
{
this.Model = paramModel;
}
public void SetView(IVehicleView paramView)
{
this.View = paramView;
}
public void RequestAccelerate(int paramAmount)
{
if(Model != null)
{
Model.Accelerate(paramAmount);
if(View != null) SetView();
}
}
public void RequestDecelerate(int paramAmount)
{
if(Model != null)
{
Model.Decelerate(paramAmount);
if(View != null) SetView();
}
}
public void RequestTurn(RelativeDirection paramDirection)
{
if(Model != null)
{
Model.Turn(paramDirection);
if(View != null) SetView();
}
}
#endregionpublic void SetView()
{
if(Model.Speed >= Model.MaxSpeed)
{
View.DisableAcceleration();
View.EnableDeceleration();
}
else if(Model.Speed <= Model.MaxReverseSpeed)
{
View.DisableDeceleration();
View.EnableAcceleration();
}
else{
View.EnableAcceleration();
View.EnableDeceleration();
}
if(Model.Speed >= Model.MaxTurnSpeed)
{
View.DisableTurning();
}
else{
View.EnableTurning();
}
}
}

Here's our ACME200SportsCar class (which extends the Automobile abstract class which implements the IVehicleModel interface):
public class ACME2000SportsCar:Automobile
{
public ACME2000SportsCar(string paramName):base(250, 40, -20, paramName){}
public
ACME2000SportsCar(string paramName, int paramMaxSpeed, int paramMaxTurnSpeed, int paramMaxReverseSpeed):base(paramMaxSpeed, paramMaxTurnSpeed, paramMaxReverseSpeed, paramName){}
}

And now for our View...
Now we have to create the last of our three ACME MVC components... the View! 

We'll create a AutoView user control and have it implement the IVehicleView interface. The AutoView component will have references to our control and model interfaces:


public class AutoView : System.Windows.Forms.UserControl, IVehicleView
{
private IVehicleControl Control = new ACME.AutomobileControl();
private IVehicleModel Model = new ACME.ACME2000SportsCar("Speedy");
}

We also need to wire everything up in the constructor for the UserControl.
public AutoView()
{
// This call is required by the Windows.Forms Form Designer.InitializeComponent();
WireUp(Control, Model);
}
public void WireUp(IVehicleControl paramControl, IVehicleModel paramModel)
{
// If we're switching Models, don't keep watching// the old one! if(Model != null)
{
Model.RemoveObserver(this);
}
Model = paramModel;
Control = paramControl;
Control.SetModel(Model);
Control.SetView(this);
Model.AddObserver(this);
}


Next, we'll add our buttons, a label to display the status of the ACME2000 Sports Car and a status bar just for kicks and fill out the code for all the buttons. 
Model View Control Buttons

private void btnAccelerate_Click(object sender, System.EventArgs e)
{
Control.RequestAccelerate(int.Parse(this.txtAmount.Text));
}
private void btnDecelerate_Click(object sender, System.EventArgs e)
{
Control.RequestDecelerate(int.Parse(this.txtAmount.Text));
}
private void btnLeft_Click(object sender, System.EventArgs e)
{
Control.RequestTurn(RelativeDirection.Left);
}
private void btnRight_Click(object sender, System.EventArgs e)
{
Control.RequestTurn(RelativeDirection.Right);
}

Add a method to update the interface...

public void UpdateInterface(IVehicleModel auto)
{
this.label1.Text = auto.Name + " heading " + auto.Direction.ToString() + " at speed: " + auto.Speed.ToString();
this.pBar.Value = (auto.Speed>0)? auto.Speed*100/auto.MaxSpeed : auto.Speed*100/auto.MaxReverseSpeed;
}


Finally, we'll wire up the IVehicleView interface methods...

public void DisableAcceleration()
{
this.btnAccelerate.Enabled = false;
}
public void EnableAcceleration()
{
this.btnAccelerate.Enabled = true;
}
public void DisableDeceleration()
{
this.btnDecelerate.Enabled = false;
}
public void EnableDeceleration()
{
this.btnDecelerate.Enabled = true;
}
public void DisableTurning()
{
this.btnRight.Enabled = this.btnLeft.Enabled = false;
}
public void EnableTurning()
{
this.btnRight.Enabled = this.btnLeft.Enabled = true;
}
public void Update(IVehicleModel paramModel)
{
this.UpdateInterface(paramModel);
}




And we're off!!!
Now we can go for a test drive in the ACME2000 Sports Car. Everything is going as planned and then we run into an ACME executive who wants to drive a pickup truck instead of a sports car. 

Good thing we used the MVC! All we need to do is create a new ACMETruck class, wire it up, and we're in business!


public class ACME2000Truck: Automobile
{
public ACME2000Truck(string paramName):base(80, 25, -12, paramName){}
public ACME2000Truck(string paramName, int paramMaxSpeed, int paramMaxTurnSpeed, int paramMaxReverseSpeed):
base(paramMaxSpeed, paramMaxTurnSpeed, paramMaxReverseSpeed, paramName){}
}

in the AutoView, we just have to build the truck and wire it up!
private void btnBuildNew_Click(object sender, System.EventArgs e)
{
this.autoView1.WireUp(new ACME.AutomobileControl(), new ACME.ACME2000Truck(this.txtName.Text));
}

If we wanted a new Control that only allowed us to increase or decrease the speed by a maximum of 5mph, it's a snap!  Create a SlowPokeControl (same as our AutoControl, but with limits on how much a Model will be requested to accelerate)
public void RequestAccelerate(int paramAmount)
{
if(Model != null)
{
int amount = paramAmount;if(amount > 5) amount = 5;
Model.Accelerate(amount);
if(View != null) SetView();
}
}
public void RequestDecelerate(int paramAmount)
{
if(Model != null)
{
int amount = paramAmount;if(amount > 5) amount = 5;
Model.Accelerate(amount);
Model.Decelerate(amount);
if(View != null) SetView();
}
}

If we want to make our ACME2000 Truck a SlowPoke, we just wire it up in the AutoView!
private void btnBuildNew_Click(object sender, System.EventArgs e)
{
this.autoView1.WireUp(new ACME.SlowPokeControl(), new ACME.ACME2000Truck(this.txtName.Text));
}

And finally, if we wanted a web-enabled interface, all we have to do is create a web project and on the UserControl implement the IVehicleView interface!

In Conclusion...
As you can see, using the MVC to help build code to control interfaces that is very loosely coupled makes life much easier when it comes to change requests. It also makes the impact of changes negligible and you can reuse your interfaces and abstract classes almost anywhere. There are a couple of places where we can build some more flexibility in our project, especially in terms of requesting changes to our Model's state, but that will have to wait for next time.

In the meanwhile, keep the MVC in mind for your next project... You won't regret it.

GridView Insert, Edit, Update and Delete – The Ado.Net way

This demo is a continuation of my previous example “Binding GridView with Data”. If you are not familiar of binding the GridView the ado.net way then I would suggest looking at my previous example first before you proceed to this example.
Basically, this demo describes the basic way to do INSERT, EDIT, UPDATE  and DELETE data in ASPNET GridView Control using the ADO.NET way. 
STEP  1: Creating  a DataBase Table
In this demo, I presumed that you already have a basic background on how to create a simple database table. In this example, this time I used my own database called SampleDB which has Customers Table and basically contains the following field columns:
CustomerID – PK
CompanyName
ContactName
ContactTitle
Address
Country

STEP 2: Setting Up the Connection String
      <connectionStrings>
            <add name="DBConnection" connectionString="Data Source=.\SQLEXPRESS;AttachDbFilename=|DataDirectory|\SampleDB.mdf;Integrated Security=True;User Instance=True" providerName="System.Data.SqlClient"/>
      </connectionStrings>

STEP 3: Setting up the GUI
Just for the simplicity of this demo, I set up the GUI like this:
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
    <title>GridView Data Manipulation</title>
</head>
<body>
    <form id="form1" runat="server">
    <div>
        <table cellpadding="0" cellspacing="0">
            <tr>
                <td style="width: 100px; height: 19px;">
                    Company ID</td>
                <td style="width: 100px; height: 19px;">
                    Company</td>
                <td style="width: 100px; height: 19px;">
                    Name</td>
                <td style="width: 100px; height: 19px;">
                    Title</td>
                <td style="width: 100px; height: 19px;">
                    Address</td>
                <td style="width: 100px; height: 19px;">
                    Country</td>
            </tr>
            <tr>
                <td style="width: 100px">
                    <asp:TextBox ID="TextBox1" runat="server"/></td>
                <td style="width: 100px">
                    <asp:TextBox ID="TextBox2" runat="server"/></td>
                <td style="width: 100px">
                    <asp:TextBox ID="TextBox3" runat="server"/></td>
                <td style="width: 100px">
                    <asp:TextBox ID="TextBox4" runat="server"/></td>
                <td style="width: 100px">
                    <asp:TextBox ID="TextBox5" runat="server"/></td>
                <td style="width: 100px">
                    <asp:TextBox ID="TextBox6" runat="server"/></td>
                <td style="width: 100px">
                    <asp:Button ID="Button1" runat="server" Text="Add New" OnClick="Button1_Click" /></td>
            </tr>
        </table>
       
        <asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="false" ShowFooter="true">
        <Columns>
            <asp:BoundField DataField="CustomerID" HeaderText="ID" ReadOnly="true"/>
            <asp:BoundField DataField="CompanyName" HeaderText="Company"/>
            <asp:BoundField DataField="ContactName" HeaderText="Name"/>
            <asp:BoundField DataField="ContactTitle" HeaderText="Title" />
            <asp:BoundField DataField="Address" HeaderText="Address"/>
            <asp:BoundField DataField="Country" HeaderText="Country"/>
        </Columns>
        </asp:GridView>
    </div>
    </form>
</body>
</html>

Note:  I have set the CustomerID field to ReadOnly so that the field cannot be edited.
STEP 4: Binding GridView with Data
I will not elaborate on this step because I already describe the details in my previous example about “Binding GridView with Data”. Here are the code blocks for binding the GridView.
public partial class _Default : System.Web.UI.Page
{
    protected void Page_Load(object sender, EventArgs e)
    {
        if (!IsPostBack)
        {
            BindGridView();
        }
    }

    private string GetConnectionString()
    {
        return System.Configuration.ConfigurationManager.ConnectionStrings["DBConnection"].ConnectionString;
    }

    #region Bind GridView
    private void BindGridView()
    {
        DataTable dt = new DataTable();
        SqlConnection connection = new SqlConnection(GetConnectionString());
        try
        {
            connection.Open();
            string sqlStatement = "SELECT Top(10)* FROM Customers";
            SqlCommand cmd = new SqlCommand(sqlStatement, connection);
            SqlDataAdapter sqlDa = new SqlDataAdapter(cmd);

              sqlDa.Fill(dt);
              if (dt.Rows.Count > 0)
              {
                GridView1.DataSource = dt;
                GridView1.DataBind();
              }
        }
        catch (System.Data.SqlClient.SqlException ex)
        {
                string msg = "Fetch Error:";
                msg += ex.Message;
                throw new Exception(msg);
        }
        finally
        {
            connection.Close();
        }
    }
    #endregion
}

Now, we already know how to bind our GridView with data from database. So let’s proceed on adding a new data in GridView.
STEP 5: Adding New Data in GridView
As you have noticed in STEP 2, we have added six TextBox and a Button in the web form in order for us to type the information there and Insert them to the database. Now let’s create a method for executing the Update or Insert.
Here are the code blocks for our Insert and Update method in the code behind:
#region Insert New or Update Record
    private void UpdateOrAddNewRecord(string ID, string Company, string Name, string Title, string Address, string Country, bool isUpdate)
    {
        SqlConnection connection = new SqlConnection(GetConnectionString());
        string sqlStatement = string.Empty;

        if (!isUpdate)
        {
            sqlStatement = "INSERT INTO Customers"+
"(CustomerID,CompanyName,ContactName,ContactTitle,Address,Country)" +
"VALUES (@CustomerID,@CompanyName,@ContactName,@ContactTitle,@Address,@Country)";
        }
        else
        {
            sqlStatement = "UPDATE Customers" +
                           "SET CompanyName = @CompanyName,
                           ContactName = @ContactName," +
                           "ContactTitle = @ContactTitle,Address = 
                           @Address,Country = @Country" +
                           "WHERE CustomerID = @CustomerID,";
        }
        try
        {
            connection.Open();
            SqlCommand cmd = new SqlCommand(sqlStatement, connection);
            cmd.Parameters.AddWithValue("@CustomerID", ID);
            cmd.Parameters.AddWithValue("@CompanyName", Company);
            cmd.Parameters.AddWithValue("@ContactName", Name);
            cmd.Parameters.AddWithValue("@ContactTitle", Title);
            cmd.Parameters.AddWithValue("@Address", Address);
            cmd.Parameters.AddWithValue("@Country", Country);
            cmd.CommandType = CommandType.Text;
            cmd.ExecuteNonQuery();
        }
        catch (System.Data.SqlClient.SqlException ex)
        {
            string msg = "Insert/Update Error:";
            msg += ex.Message;
            throw new Exception(msg);

        }
        finally
        {
            connection.Close();
        }
    }
    #endregion

The UpdateOrAddNewRecord is a method that takes seven parameters.  Six of those paramaters basically comes from the TextBox values that were entered in the page. The last parameter is a boolean value which tells the method whether to execute an Insert (false) or Update (true). Default is true.
Here’s the code block for calling the method UpdateOrAddNewRecord on Button_Click event and pass the corresponding parameters needed:
    protected void Button1_Click(object sender, EventArgs e)
    {
        UpdateOrAddNewRecord(TextBox1.Text, TextBox2.Text, TextBox3.Text, TextBox4.Text, TextBox5.Text, TextBox6.Text, false);
        //Re Bind GridView to reflect changes made
        BindGridView();
    }

As you can see from above, We have called the BindGridView() method again in order to reflect the changes made and display the new added data in the GridView. See output below with red mark.

STEP 6: Edit and Update Records In GridView
One of the good things about GridView is that it provides a built-in CommandField Buttons which allows us to perform certain actions like editing, updating,deleting and selecting of GridView data.
To add those command fields mentioned in the GridView you can follow these few steps below:
1.       Switch to Design View
2.       Right Click on the GridView and Select  --> Show Smart Tag --> Add New Columns
3.       On the List Select CommandField
4.       Check Delete and Edit/Update options then OK

As you can see the Edit and Delete CommandField are automatically added in the last column of GridView.  Now we can start to write our codes for editing and updating the information in the GridView.

In-order to perform Edit and Update in GridView we need to use three events ( GridView_RowEditing, GridView_RowCancelingEdit , GridView_RowUpdating). For those who do not know on how to generate Events in GridView you can follow these steps below:

1.       Switch to Design View in Visual Studio Designer
2.       Click on the GridView
3.       Navigate to the GridView Property Pane and then SWITCH to Event Properties
4.       From there you would be able to find the list of events including those three  events mentioned above
5.       Double Click on that to generate the Event handler for you
6.       Then write the codes there

Here’s the code for each events:

protected void GridView1_RowEditing(object sender, GridViewEditEventArgs e)
{
        GridView1.EditIndex = e.NewEditIndex; // turn to edit mode
        BindGridView(); // Rebind GridView to show the data in edit mode
}

protected void GridView1_RowCancelingEdit(object sender, GridViewCancelEditEventArgs e)
{
        GridView1.EditIndex = -1; //swicth back to default mode
        BindGridView(); // Rebind GridView to show the data in default mode
}

protected void GridView1_RowUpdating(object sender, GridViewUpdateEventArgs e)
{
        //Accessing Edited values from the GridView
        string id = GridView1.Rows[e.RowIndex].Cells[0].Text; //ID
        string company = ((TextBox)GridView1.Rows[e.RowIndex].Cells[1].Controls[0]).Text; //Company
        string name = ((TextBox)GridView1.Rows[e.RowIndex].Cells[2].Controls[0]).Text; //Name
        string title = ((TextBox)GridView1.Rows[e.RowIndex].Cells[3].Controls[0]).Text; //Title
        string address = ((TextBox)GridView1.Rows[e.RowIndex].Cells[4].Controls[0]).Text; //Address
        string country = ((TextBox)GridView1.Rows[e.RowIndex].Cells[5].Controls[0]).Text; //Country

        UpdateOrAddNewRecord(id,company,name,title,address,country,true); // call update method
        GridView1.EditIndex = -1;
        BindGridView(); // Rebind GridView to reflect changes made
}

STEP 7: Perform Delete in GridView

Since we are using the Built-in Delete CommandField Button in GridView, we can use the GridView_RowDeleting event to delete specific row in GridView.

Here’s the code block for the Delete method:
#region Delete Record
    private void DeleteRecord(string ID)
    {
        SqlConnection connection = new SqlConnection(GetConnectionString());
        string sqlStatement = "DELETE FROM Customers WHERE CustomerID = @CustomerID";
        try
        {
            connection.Open();
            SqlCommand cmd = new SqlCommand(sqlStatement, connection);
            cmd.Parameters.AddWithValue("@CustomerID", ID);
            cmd.CommandType = CommandType.Text;
            cmd.ExecuteNonQuery();
        }
        catch (System.Data.SqlClient.SqlException ex)
        {
            string msg = "Deletion Error:";
            msg += ex.Message;
            throw new Exception(msg);

        }
        finally
        {
            connection.Close();
        }
    }
#endregion

Here’s the code block for calling the delete method at RowDeleting event
protected void GridView1_RowDeleting(object sender, GridViewDeleteEventArgs e)
{
   string id = GridView1.Rows[e.RowIndex].Cells[0].Text; get the id of the selected row
   DeleteRecord(id);//call delete method
   BindGridView();//rebind grid to reflect changes made
}