I'm working with two stored procedures in an ASP.NET button function. While I get an error message based on the results that the invoice number is already dispatched from the other stored procedure, it still moves to the other stored procedure and executes it.
If the user gets this error message:
This invoice num was already dispatched!
then it shouldn't move on to this aspect of the function
protected void Button2_Click(object sender, EventArgs e)
{
try
{
for (int i = GridView2.Rows.Count - 1; i >= 0; i--)
{
var row = GridView2.Rows[i];
CheckBox chk = row.FindControl("chkInvoice") as CheckBox;
//CheckBox chk = (CheckBox)GridView2.Rows[i].Cells[0].FindControl("CheckBox3");
if (chk != null && chk.Checked)
{
string strSQLconstring = System.Configuration.ConfigurationManager.ConnectionStrings["TWCL_OPERATIONSConnectionString"].ToString();
using (SqlConnection objConnection = new SqlConnection(strSQLconstring))
{
objConnection.Open();
using (SqlTransaction transaction = objConnection.BeginTransaction())
{
string SID = GridView2.Rows[i].Cells[3].Text.Trim();
SqlDataReader myReader = null;
using (SqlCommand command = new SqlCommand("PP_SelectStatus", objConnection, transaction))
{
command.CommandType = CommandType.StoredProcedure;
command.Parameters.AddWithValue("#invoiceNum", SID);
command.Parameters.AddWithValue("#custPONum", GridView2.Rows[i].Cells[4].Text.Trim());
myReader = command.ExecuteReader();
if (myReader.Read())
{
string invoice1 = (myReader["status"].ToString());
if (invoice1 == "0")
{
ClientScript.RegisterClientScriptBlock(this.GetType(), "alert", "alert('This invoice num was already dispatched!')", true);
}
myReader.Close();
}
}
else if (invoice1=="1")
{
using (SqlCommand cmd = new SqlCommand("PP_RemoveInvoice", objConnection, transaction))
{
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.AddWithValue("#loadSheetNum", txtDispatchNum.Text);
cmd.Parameters.AddWithValue("#invoiceNum", SID);
cmd.Parameters.AddWithValue("#removeUser", lblUsername.Text.Replace("Welcome", ""));
**int a = cmd.ExecuteNonQuery();**
cmd.Dispose();
if (a > 0)
{
dt.Rows.RemoveAt(i);
////Read invoice qty from grid view 2
string invoice = GridView2.Rows[i].Cells[5].Text.ToString();
decimal invoiceTotal = Convert.ToDecimal(txtInvoiceTotal.Text) - Convert.ToDecimal(invoice);
txtInvoiceTotal.Text = invoiceTotal.ToString();
////Read invoice weight from grid view 2
string weight = GridView2.Rows[i].Cells[6].Text.ToString();
decimal invoiceWeight = Convert.ToDecimal(txtQtyWeight.Text) - Convert.ToDecimal(weight);
txtQtyWeight.Text = invoiceWeight.ToString();
lblError.ForeColor = Color.Green;
lblError.Text = "Selected record(s) successfully updated";
}
else
{
lblError.ForeColor = Color.Red;
lblError.Text = " Record has not yet been recorded";
}
}
//objConnection.Close();
transaction.Commit();
}
}
}
//Button2.Visible = false;
//showData();
GridView2.DataSource = dt;
GridView2.DataBind();
txtInvoiceCount.Text = dt.Rows.Count.ToString();
}
}
}
catch (Exception ex)
{
if (ex.Message.StartsWith("Violation of PRIMARY KEY constraint"))
{
lblError.ForeColor = Color.Red;
lblError.Text = " This invoice number was remove from dispatch sheet before!!";
}
else
{
// re-throw the error if you haven't handled it
lblError.Text = ex.Message;
throw;
}
}
}
You have a very, very simple logic error, but it is incredibly hard to see because your code is such a mess. Therefore, my answer is:
REFACTOR REFACTOR REFACTOR
It is important to get into the habit of writing short functions and controlling their inputs and outputs. If you don't do this, even a fairly trivial operation like this one gets very confusing and error-prone.
Here is an example of how to organize things. We remove most of the code from the click handler:
protected void DeleteButton_Click(object sender, EventArgs e)
{
for (int i = GridView2.Rows.Count - 1; i >= 0; i--)
{
var row = GridView2.Rows[i];
if (IsChecked(row))
{
var result = ProcessRow(row, i);
DisplayResult(i, result);
}
}
}
Firstly, notice it has a meaningful name. These become very important as your application grows. Also, look how short it is! Where did all the code go? Well, it went into two separate methods, which are now short enough for us to view on one page-- a common requirement that IT organizations impose on their programmers, to avoid spaghetti code.
protected TransactionResult ProcessRow(GridViewRow row, int index)
{
var SID = GridView2.Rows[index].Cells[3].Text.Trim();
var custPONum = GridView2.Rows[index].Cells[4].Text.Trim();
var loadSheetNum = txtDispatchNum.Text;
var removeUser = lblUsername.Text.Replace("Welcome", "");
return ExecuteInvoiceTransaction(SID, custPONum, loadSheetNum, removeUser);
}
And
public void DisplayResult(int rowIndex, TransactionResult result)
{
switch result
{
case TransactionResult.Success:
dt.Rows.RemoveAt(rowIndex);
DisplayTotals(rowIndex);
DisplaySuccess("Selected record(s) successfully updated");
break;
case TransactionResult.AlreadyDispatched;
ClientScript.RegisterClientScriptBlock(this.GetType(), "alert", "alert('This invoice num was already dispatched!')", true);
break;
case TransactionResult.RecordNotRecorded;
DisplayError("Record has not yet been recorded");
break;
case TransactionResult.AlreadyRemoved:
DisplayError("This invoice number was remove from dispatch sheet before!!");
break;
}
}
These methods in turn call a variety of helper methods, each of which does one thing and one thing only. This could be referred to as separation of concerns, which is really important for structured code.
Here's the rest of the methods:
enum TransactionResult
{
Success,
AlreadyDispatched,
RecordNotRecorded,
AlreadyRemoved
}
private bool ExecuteSelectStatus(SqlConnection connection, SqlTransaction transaction, string invoiceNum, string custPONum)
{
using (SqlCommand command = new SqlCommand("PP_SelectStatus", objConnection, transaction))
{
command.CommandType = CommandType.StoredProcedure;
command.Parameters.AddWithValue("#invoiceNum", invoiceNum);
command.Parameters.AddWithValue("#custPONum", custPONum);
using (var myReader = command.ExecuteReader())
{
if (myReader.Read())
{
string invoice1 = (myReader["status"].ToString());
if (invoice1 == "0")
{
return false;
}
}
}
return true;
}
}
private int ExecuteRemoveInvoice(SqlConnection objConnection, SqlTransaction transaction, string loadSheetNum, string invoiceNum, string removeUser)
{
try
{
using (SqlCommand cmd = new SqlCommand("PP_RemoveInvoice", objConnection, transaction))
{
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.AddWithValue("#loadSheetNum", loadSheetNum);
cmd.Parameters.AddWithValue("#invoiceNum", invoiceNum);
cmd.Parameters.AddWithValue("#removeUser", removeUser);
return cmd.ExecuteNonQuery();
}
}
catch (SqlException ex)
{
if (ex.Number == 2627) //Primary key violation
{
return -1;
}
}
}
protected TransactionResult ExecuteInvoiceTransaction(string invoiceNum, string custPONum, string loadSheetNum, string removeUser)
{
var strSQLconstring = System.Configuration.ConfigurationManager.ConnectionStrings["TWCL_OPERATIONSConnectionString"].ToString();
using (SqlConnection objConnection = new SqlConnection(strSQLconstring))
{
objConnection.Open();
using (SqlTransaction transaction = objConnection.BeginTransaction())
{
var ok = ExecuteSelectStatus(objConnection, transaction, invoiceNum, custPONum);
if (!ok) return TransactionResult.AlreadyDispatched;
var a = ExecuteRemoveInvoice(objConnection, transaction, loadSheetNum, invoiceNum, removeUser);
switch a
{
case -1:
return TransactionResult.AlreadyRemoved;
case 0:
return TransactionResult.RecordNotRecorded;
default:
transaction.Commit();
return TransactionResult.Success;
}
}
}
}
public void DisplayTotals(int i)
{
////Read invoice qty from grid view 2
string invoice = GridView2.Rows[i].Cells[5].Text;
decimal invoiceTotal = Convert.ToDecimal(txtInvoiceTotal.Text) - Convert.ToDecimal(invoice);
txtInvoiceTotal.Text = invoiceTotal.ToString();
////Read invoice weight from grid view 2
string weight = GridView2.Rows[i].Cells[6].Text();
decimal invoiceWeight = Convert.ToDecimal(txtQtyWeight.Text) - Convert.ToDecimal(weight);
txtQtyWeight.Text = invoiceWeight.ToString();
}
public void DisplaySuccess(string message)
{
lblError.ForeColor = Color.Green;
lblError.Text = message;
}
public void DisplayError(string message)
{
lblError.ForeColor = Color.Red;
lblError.Text = message;
}
A few things to note:
You don't need to call Dispose() if you are using using.
You should always catch the most specific exception possible, per Microsoft's guidance. My example does this.
The exception handling for the primary key error is isolated into the method that calls the stored procedure. The overall business logic shouldn't have to know details about the SQL implementation. I've shown how you can identify the specific error based on this post.
Because there are four possible outcomes, I added an enumeration called TransactionResult so we could return the status to the caller easily.
Some of these methods are short-- just two lines-- and that is OK. The main reason to separate them out is to give them a meaningful name and make the code shorter and easier to read.
This code is much more structured but it could still be improved! In many implementations, the code that accesses the database is actually moved to a completely different layer or project.
See if this works. Moved your if/else together:
protected void Button2_Click(object sender, EventArgs e)
{
try
{
for (int i = GridView2.Rows.Count - 1; i >= 0; i--)
{
var row = GridView2.Rows[i];
CheckBox chk = row.FindControl("chkInvoice") as CheckBox;
if (chk != null && chk.Checked)
{
string strSQLconstring = System.Configuration.ConfigurationManager.ConnectionStrings["TWCL_OPERATIONSConnectionString"].ToString();
using (SqlConnection objConnection = new SqlConnection(strSQLconstring))
{
objConnection.Open();
using (SqlTransaction transaction = objConnection.BeginTransaction())
{
string SID = GridView2.Rows[i].Cells[3].Text.Trim();
SqlDataReader myReader = null;
using (SqlCommand command = new SqlCommand("PP_SelectStatus", objConnection, transaction))
{
command.CommandType = CommandType.StoredProcedure;
command.Parameters.AddWithValue("#invoiceNum", SID);
command.Parameters.AddWithValue("#custPONum", GridView2.Rows[i].Cells[4].Text.Trim());
myReader = command.ExecuteReader();
if (myReader.Read())
{
string invoice1 = (myReader["status"].ToString());
if (invoice1 == "0")
{
ClientScript.RegisterClientScriptBlock(this.GetType(), "alert", "alert('This invoice num was already dispatched!')", true);
}
else if (invoice1 == "1")
{
using (SqlCommand cmd = new SqlCommand("PP_RemoveInvoice", objConnection, transaction))
{
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.AddWithValue("#loadSheetNum", txtDispatchNum.Text);
cmd.Parameters.AddWithValue("#invoiceNum", SID);
cmd.Parameters.AddWithValue("#removeUser", lblUsername.Text.Replace("Welcome", ""));
int a = cmd.ExecuteNonQuery();
cmd.Dispose();
if (a > 0)
{
dt.Rows.RemoveAt(i);
////Read invoice qty from grid view 2
string invoice = GridView2.Rows[i].Cells[5].Text.ToString();
decimal invoiceTotal = Convert.ToDecimal(txtInvoiceTotal.Text) - Convert.ToDecimal(invoice);
txtInvoiceTotal.Text = invoiceTotal.ToString();
////Read invoice weight from grid view 2
string weight = GridView2.Rows[i].Cells[6].Text.ToString();
decimal invoiceWeight = Convert.ToDecimal(txtQtyWeight.Text) - Convert.ToDecimal(weight);
txtQtyWeight.Text = invoiceWeight.ToString();
lblError.ForeColor = Color.Green;
lblError.Text = "Selected record(s) successfully updated";
}
else
{
lblError.ForeColor = Color.Red;
lblError.Text = " Record has not yet been recorded";
}
}
//objConnection.Close();
transaction.Commit();
}
}
}
GridView2.DataSource = dt;
GridView2.DataBind();
txtInvoiceCount.Text = dt.Rows.Count.ToString();
}
}
}
}
}
catch (Exception ex)
{
if (ex.Message.StartsWith("Violation of PRIMARY KEY constraint"))
{
lblError.ForeColor = Color.Red;
lblError.Text = " This invoice number was remove from dispatch sheet before!!";
}
else
{
// re-throw the error if you haven't handled it
lblError.Text = ex.Message;
throw;
}
}
}
}
Hi Friends i have created a single asp.net page(c#) with multiple grid view to display records. I have multiple command button to show records in these grid.
I am using single button to clear the row selection in grid but it is not working.
Please help me...
protected void btnClearGridSelection_Click(object sender, EventArgs e)
{
if (GridView1.Visible == true)
{
GridView1.SelectedIndex = -1;
}
if (GridView1.Visible == true)
{
GridViewSearch.SelectedIndex = -1;
}
if (GridView1.Visible == true)
{
GridViewState.SelectedIndex = -1;
}
if (GridView1.Visible == true)
{
GridViewDistrict.SelectedIndex = -1;
}
if (GridView1.Visible == true)
{
GridViewType.SelectedIndex = -1;
}
if (GridView1.Visible == true)
{
GridViewEmployee.SelectedIndex = -1;
}
}
//---------------------updating my question with new problem-------------
Now i am able to to clear the selection from row but facing new problem.......When i am clicking on show(to show results state wise) button it is showing results and also clearing the selection when clicking on clear selection button with no problems....but when i click on another show button(to show results district wise) to show results it is showing results but when i select the row and click on clear selection button it is showing both grid with records......please help how to hide state Grid when i am Clicking on Clear Selection Button while using District grid......i am posting the code which i am using on Button Click....
.......clear selection....Button click:
protected void btnClearGridSelection_Click(object sender, EventArgs e)
{ GridView1.SelectedIndex = -1;
GridViewSearch.SelectedIndex = -1;
GridViewState.SelectedIndex = -1;
GridViewDistrict.SelectedIndex = -1;
GridViewType.SelectedIndex = -1;
GridViewEmployee.SelectedIndex = -1;
}
.......State Grid....Button click:
protected void btnState_Click(object sender, EventArgs e)
{
GridView1.Visible = false;
//GridViewState.Visible = true;
GridViewDistrict.Visible = false;
GridViewSearch.Visible = false;
GridViewType.Visible = false;
GridViewEmployee.Visible = false;
btnClearGridSelection.Visible = true;
string d2 = ddlState.Text;
string strquery = "select * from tblAsset2 where v_State=#d2";
if (con.State != ConnectionState.Closed)
{
con.Close();
}
con.Open();
try
{
SqlCommand cmd = new SqlCommand(strquery, con);
cmd.Parameters.AddWithValue("#d2", d2);
SqlDataAdapter da = new SqlDataAdapter(cmd);
DataSet ds = new DataSet();
da.Fill(ds);
GridViewState.DataSource = ds;
GridViewState.DataBind();
int rowCount = GridViewState.Rows.Count;
if (rowCount <= 0)
{
Label67.Visible = true;
GridViewState.Visible = false;
Label67.Text = "Sorry!....Records not found.";
}
else
{
GridViewState.Visible = true;
Label67.Visible = false;
}
}
catch (Exception ex)
{
Response.Write(ex);
}
finally
{
con.Close();
}
}
....................District Grid....Button click:
protected void btnDistrict_Click(object sender, EventArgs e)
{
GridView1.Visible = false;
GridViewDistrict.Visible = false;
//GridViewDistrict.Visible = true;
GridViewSearch.Visible = false;
GridViewType.Visible = false;
GridViewEmployee.Visible = false;
btnClearGridSelection.Visible = true;
string d2 = ddlDistrict.Text;
string strquery = "select * from tblAsset2 where v_District=#d2";
if (con.State != ConnectionState.Closed)
{
con.Close();
}
con.Open();
try
{
SqlCommand cmd = new SqlCommand(strquery, con);
cmd.Parameters.AddWithValue("#d2", d2);
SqlDataAdapter da = new SqlDataAdapter(cmd);
DataSet ds = new DataSet();
da.Fill(ds);
GridViewDistrict.DataSource = ds;
GridViewDistrict.DataBind();
int rowCount = GridViewDistrict.Rows.Count;
if (rowCount <= 0)
{
Label67.Visible = true;
GridViewDistrict.Visible = false;
Label67.Text = "Sorry!....Records not found.";
}
else
{
GridViewDistrict.Visible = true;
Label67.Visible = false;
}
}
catch (Exception ex)
{
Response.Write(ex);
}
finally
{
con.Close();
}
}
I resolved my problem and it may help someone else so i am posting it.. i have written wrong line:- GridViewState.Visible = true; // i have commented this line and error gone
protected void GridViewState_RowCreated(object sender, GridViewRowEventArgs e)
{
GridViewState.Visible = true; // i have commented this line and error gone
}
Would someone who knows DeveExpess ASPxGridView take a look at this.
Is this the best/correct way to use the grid to edit a List?
I have an object of Type ItemModel and the code below is used to allow an ASP.NET Web Site user to do CRUD operations on list of ItemModels.
My problem is that it seems too complex and I suspect I am not taking good advantage of the Grid.
For simplicity, I have left the Database Access Code that will load and save the list of ItemModels.
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
BindGrid();
}
protected void OnRowInserting(object sender, ASPxDataInsertingEventArgs e)
{
IList<ItemModel> itemModels = CachedModels;
int lineID = 0;
if (itemModels .Count > 0)
{
lineID = itemModels[itemModels.Count - 1].LineID + 1;
}
ItemModel itemModel = new ItemModel()
{
, Code = e.NewValues["Code"] == null ? string.Empty : e.NewValues["Code"].ToString()
, Name = e.NewValues["Name"] == null ? string.Empty : e.NewValues["Name"].ToString()
, DateCreated = DateTime.Now
, DateUpdated = DateTime.Now
};
itemModels.Add(itemModel);
CachedModels = itemModels;
ASPxGridView aspxGridView = (ASPxGridView)sender;
aspxGridView.CancelEdit();
e.Cancel = true;
BindGrid();
}
protected void OnRowUpdating(object sender, ASPxDataUpdatingEventArgs e)
{
IList<ItemModel> itemModels = CachedModels;
int lineID = Convert.ToInt32(e.Keys[0].ToString());
ItemModel itemModel = null;
foreach (ItemModel model in itemModels)
{
if (model.LineID == lineID)
{
itemModel = model;
break;
}
}
if (itemModel != null)
{
itemModel.Code = e.NewValues["Code"] == null ? string.Empty : e.NewValues["Code"].ToString();
itemModel.Name = e.NewValues["Name"] == null ? string.Empty : e.NewValues["Name"].ToString();
containerItemModel.DateUpdated = DateTime.Now;
itemModels[lineID] = itemModel;
CachedModels = itemModels;
}
ASPxGridView aspxGridView = (ASPxGridView)sender;
aspxGridView.CancelEdit();
e.Cancel = true;
BindGrid();
}
protected void OnRowDeleting(object sender, ASPxDataDeletingEventArgs e)
{
IList<ItemModel> itemModels = CachedModels;
int lineID = Convert.ToInt32(e.Keys[0].ToString());
ItemModel itemModel = null;
foreach (ItemModel model in itemModels)
{
if (model.LineID == lineID)
{
itemModel = model;
break;
}
}
if (itemModel != null)
{
itemModels.Remove(itemModel);
CachedModels = itemModels;
}
ASPxGridView aspxGridView = (ASPxGridView)sender;
aspxGridView.CancelEdit();
e.Cancel = true;
BindGrid();
}
private void BindGrid()
{
grdItems.DataSource = CachedModels;
grdItems.DataBind();
}
private IList<ItemModel> CachedModels
{
get
{
List<ItemModel> models= (List<ItemModel>)Session["ItemModels"];
if (models == null)
{
models= new List<ItemModel>();
Session["ItemModels"] = models;
}
return models;
}
set
{
Session["ItemModels"] = value;
}
}
I believe your current code is quite correct.
Here is the suggested way from DX:
ASPxGridView - How to implement CRUD operations with a custom data source
I am trying to implement a Login validation using C# 2005 in ASP.net 2.0 web application. The SQL Server database contains a table named "UserList" with columns LoginId, Password and Role. The Login webform should authenticate the LoginId and password and depending upon the Role assigned to that user/visitor should redirect to a specific webform with a pre-defined menu options. The role might be Admin, DEO, Accounts or Member. How should I implement it? I have tried the following:
protected void Login1_Authenticate(object sender, AuthenticateEventArgs e)
{
try
{
string uname = Login1.UserName.Trim();
string password = Login1.Password.Trim();
int flag = AuthenticateUser(uname, password);
if (flag == 1)
{
e.Authenticated = true;
Login1.DestinationPageUrl = "~/MenuAdmin.aspx";
}
else if (flag == 2)
{
e.Authenticated = true;
Login1.DestinationPageUrl = "~/MenuDEO.aspx";
}
else if (flag == 3)
{
e.Authenticated = true;
Login1.DestinationPageUrl = "~/MenuAccts.aspx";
}
else if (flag == 4)
{
e.Authenticated = true;
Login1.DestinationPageUrl = "~/MenuMember.aspx";
}
else
{
e.Authenticated = false;
}
}
catch (Exception)
{
e.Authenticated = false;
}
}
private int AuthenticateUser(string uname, string password)
{
int bflag = 0;
string connString = ConfigurationManager.ConnectionStrings["LoginDemoConnString"].ConnectionString;
string strSQL = "Select * FROM UserList where ULoginId ='" + uname + "' AND UPassword ='" + password + "'";
DataTable dt = new DataTable();
SqlConnection m_conn;
SqlDataAdapter m_dataAdapter;
try
{
m_conn = new SqlConnection(connString);
m_conn.Open();
m_dataAdapter = new SqlDataAdapter(strSQL, m_conn);
m_dataAdapter.Fill(dt);
m_conn.Close();
}
catch (Exception ex)
{
dt = null;
}
finally
{
//m_conn.Close();
}
if (dt.Rows.Count > 0)
{
if (dt.Rows[0][3].ToString() == "Administrator")
bflag = 1;
else if (dt.Rows[0][3].ToString() == "DEO")
bflag = 2;
else if (dt.Rows[0][3].ToString() == "Accts")
bflag = 3;
else
bflag = 4;
}
return bflag;
}
Well first of all I guess each role in the sql table has id so you can get rid of the ifs in the AuthenticateUser and just return the id. Or you can also return the actual role and just do something with this data in the Login1_Authenticate function.
Now you can also get rid of the ifs in the Login1_Authenticate function if you will use dictionary where the key is role and value is pageURL so you can just write something like that:
int flag = AuthenticateUser();
Login1.DestinationPageUrl = roles.ElementAt(flag).Value;
How can I change the default sort direction when clicking a column in an ASP.NET GridView?
I would like it so that when a new column is clicked, it sorts in DESC order by default instead of ASC.
protected void OnGridViewSorting(object sender, GridViewSortEventArgs e)
{
DataTable dataTable = RoomsGrid.DataSource as DataTable;
if (dataTable != null)
{
DataView dataView = new DataView(dataTable);
dataView.Sort = e.SortExpression + " " +ConvertSortDirectionToSql(e.SortDirection);
RoomsGrid.DataSource = dataView;
RoomsGrid.DataBind();
}
}
private string ConvertSortDirectionToSql(SortDirection sortDirection)
{
string newSortDirection = String.Empty;
switch (sortDirection)
{
case SortDirection.Ascending: newSortDirection = "ASC"; break;
case SortDirection.Descending: newSortDirection = "DESC"; break;
}
return newSortDirection;
}
Here's an example of how it behaves now:
http://www.venuefinder.com/venues/national_motorcycle_museum/V4204/meeting-rooms/
You can't change the GridView's default sort direction but since you are using a function to get the sort direction, you can do it manually as mentioned in the following link - http://www.mikepope.com/blog/DisplayBlog.aspx?permalink=1418
With reference to the code above, you can do the following to accomplish what you are asking:
private string ConvertSortDirectionToSql(SortDirection sortDirection)
{
string newSortDirection = String.Empty;
switch (sortDirection)
{
case SortDirection.Ascending: newSortDirection = "DESC"; break;
case SortDirection.Descending: newSortDirection = "ASC"; break;
}
return newSortDirection;
}
Hope this helps!
There's a nice MSDN article on this -- the sample it provides returns ASC as the default, but you could easily change that to DESC. Here: http://msdn.microsoft.com/en-us/library/system.web.ui.webcontrols.gridview.sorting.aspx#Y576