GridView lost sorting after paging? - asp.net

I got the below code from internet. It is working properly. I have added paging also. When I'm just sorting, it is working properly. When I am changing the page index, the sorting is lost.
Here is the client side code that set a gridview with 20 items per page, using the sort linked to the "GridView1_Sorting" method in the server side code.
Client side
<asp:GridView ID="GridView1" runat="server" DataKeyNames="eno" AutoGenerateColumns="False" PageSize="20" AllowPaging="True" AllowSorting="True" OnSorting="GridView1_Sorting" CellPadding="4">
<Columns>
<asp:TemplateField HeaderText="Employee no" SortExpression="eno">
<ItemTemplate>
<%#Eval("eno")%>
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="Emp name" SortExpression="empname">
<ItemTemplate>
<%#Eval("empname")%>
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="Salary" SortExpression="sal">
<ItemTemplate>
<%#Eval("sal")%>
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
And now the server side code:
Server side
using System.Data.SqlClient;
using System.Configuration;
using System.IO;
public partial class _Default : System.Web.UI.Page
{
SqlConnection sqlcon = new SqlConnection(ConfigurationManager.ConnectionStrings["Con"].ConnectionString);
SqlCommand sqlcmd;
SqlDataAdapter da;
DataTable dt = new DataTable();
DataTable dt1 = new DataTable();
protected void Page_Load(object sender, EventArgs e)
{
if (!Page.IsPostBack)
{
GridData();
}
}
void GridData()
{
sqlcmd = new SqlCommand("select * from emp", sqlcon);
sqlcon.Open();
da = new SqlDataAdapter(sqlcmd);
dt.Clear();
da.Fill(dt);
if (dt.Rows.Count > 0)
{
Session["dt"] = dt;
GridView1.DataSource = dt;
GridView1.DataBind();
}
}
private string GVSortDirection
{
get { return ViewState["SortDirection"] as string ?? "DESC"; }
set { ViewState["SortDirection"] = value; }
}
private string GetSortDirection()
{
switch (GVSortDirection)
{
case "ASC":
GVSortDirection = "DESC";
break;
//assign new direction as ascending order
case "DESC":
GVSortDirection = "ASC";
break;
}
return GVSortDirection;
}
protected void GridView1_Sorting(object sender, GridViewSortEventArgs e)
{
DataTable dataTable = (DataTable)Session["dt"];
if (dataTable != null)
{
DataView dataView = new DataView(dataTable);
string sortDirection = GetSortDirection();
dataView.Sort = e.SortExpression + " " + sortDirection;
GridView1.DataSource = dataView;
GridView1.DataBind();
}
}
protected void GridView1_PageIndexChanging(object sender, GridViewPageEventArgs e)
{
GridView1.PageIndex = e.NewPageIndex;
GridData();
}
}

When you page, the PageIndexChanging event is called. This in turn runs the GridData() procedure, which sets the data source for the gridview to be a data table containing records from the emp table, with no particular sort order.
What you should do is to take the code that you've written in your GridView1_Sorting event-handler, and include this within the GridData routine, so that whenever the grid is populated with data - whether when the page first loads, when the page index is changed or when the gridview is sorted - the gridview is based on a sorted dataview, rather than an unsorted data table.

The way you are maintaining SortDirection using GetSortDirection, in same fashion maintain SortExpression.
Happy coding!!!

Have a look to this article, may you will get what you want

Related

A field or property with the name 'bname' was not found on the selected data source

I know this type of question has been asked multiple times, with solved answers. I've tried them all, but none of it seems to work. Please have a look and maybe help me in understanding where I am going wrong.
.aspx
<asp:view ID="view2" runat="server">
<asp:GridView ID="gvBatches" runat="server" AutoGenerateColumns="False" CssClass="table-hover table" GridLines="None" Width="900px" ShowFooter="True" >
<columns>
<asp:BoundField DataField="bname" HeaderText="Batch Name" />
</columns>
</asp:GridView>
</asp:view>
.aspx.cs
protected void Page_Load(object sender, EventArgs e)
{
if (!Page.IsPostBack)
{
if (ViewState["query"] == null)
{
ViewState["query"] = "select course from tblCourses";
}
if (MultiView1.ActiveViewIndex == '1')
{
bindgrid1();
}
bindgrid();
}
}
protected void bindgrid1()
{
SqlConnection con = new SqlConnection(ConfigurationManager.ConnectionStrings["DBCS"].ConnectionString);
DataTable dt1 = new DataTable();
using (SqlDataAdapter sda = new SqlDataAdapter(ViewState["query"].ToString(), con))
{
sda.Fill(dt1);
}
gvBatches.DataSource = dt1;
gvBatches.DataBind();
}
if (e.CommandName == "viewbat")
{
ViewState["query"] = "select bname from tblBatches where course='" + e.CommandArgument.ToString() + "'";
MultiView1.ActiveViewIndex = 1;
}
Multiview index is changed when a LinkButton(commandName="viewbat") is clicked on a different GridView(gvCourses with datafield="course" and that works fine).
The code throws same error even if the query is changed to simple:
select * from tblBatches
Database design:
Database design is as shown, consists 'bname'

method of populate dropdownlist inside gridview

If i want to populate a DropdownList in a GridView what will be the best way? use GridView 'OnRowDataBound' event and fetch query everytime to db or get all data first and put it on datatable and do further work from this datatable ?
As your question is unclear about your requirement, I assume that you want to bind dropdownlist inside the Gridview using OnRowDataBound event of gridview.
So here are the steps:-
Add a Gridview HTML in your aspx page with DropDownList in ItemTemplate of TemplateField.
<asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="false" OnRowDataBound="OnRowDataBound">
<Columns>
<asp:BoundField HeaderText="Name" DataField="ContactName" />
<asp:TemplateField HeaderText = "Country">
<ItemTemplate>
<asp:Label ID="lblCountry" runat="server" Text='<%# Eval("Country") %>' Visible = "false" />
<asp:DropDownList ID="ddlCountries" runat="server">
</asp:DropDownList>
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
Then you need to bind the gridview with records which will come from the database.
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
GridView1.DataSource = GetData("SELECT ContactName, Country FROM Customers");
GridView1.DataBind();
}
}
private DataSet GetData(string query)
{
string conString = ConfigurationManager.ConnectionStrings["constr"].ConnectionString;
SqlCommand cmd = new SqlCommand(query);
using (SqlConnection con = new SqlConnection(conString))
{
using (SqlDataAdapter sda = new SqlDataAdapter())
{
cmd.Connection = con;
sda.SelectCommand = cmd;
using (DataSet ds = new DataSet())
{
sda.Fill(ds);
return ds;
}
}
}
}
Then the code for OnRowDataBound will follow like below :-
protected void OnRowDataBound(object sender, GridViewRowEventArgs e)
{
if (e.Row.RowType == DataControlRowType.DataRow)
{
//Find the DropDownList in the Row
DropDownList ddlCountries = (e.Row.FindControl("ddlCountries") as DropDownList);
ddlCountries.DataSource = GetData("SELECT DISTINCT Country FROM Customers");
ddlCountries.DataTextField = "Country";
ddlCountries.DataValueField = "Country";
ddlCountries.DataBind();
//Add Default Item in the DropDownList
ddlCountries.Items.Insert(0, new ListItem("Please select"));
//Select the Country of Customer in DropDownList
string country = (e.Row.FindControl("lblCountry") as Label).Text;
ddlCountries.Items.FindByValue(country).Selected = true;
}
}
See the Reference link for your reference
Also see the Working demo for your reference
Hope that helps.

how to bind gridview to sqldatasource to our own created form

I have a form and 'Add' button. when i click on add then i insert data into database and also i have sqldatasource in which i specify only select,update,delete commands. when i insert data on Add button then i want to refresh and fill the grid automatically.
my sqldatasource id is "sqldatasourceDenter" and i have specified it in my gridview datasourceID="sqldatasourceDenter".
i have tried this
GridView1.DataSourceID = sqldatasourceDenter;
it gives me the error cannot convert sqldatasource to string
i have also defined datasource but it tells both me both datasource, datasourceID cannot be defined.
I actually want to insert data on my 'Add' button then refresh the sqldataSourceDenter to fill the grid.
This is my add button click event function:
..... add_Click(object sender, EventArgs e){
..
.... /* here i have other code*/
.....
else {
string dentername = dname.Text.ToString();
string denteraddress = daddress.Text.ToString();
string dentercontact = dcontact.Text.ToString();
//create sql inset query and take to insert query ftn for execution
string dquery = string.Format("INSERT INTO Denters(D_NIC, D_Name, D_Address, D_Contact) VALUES('{0}','{1}','{2}','{3}')", denternic, dentername, denteraddress, dentercontact);
InsertIntoDB.InsertQuery(dquery);
if (InsertIntoDB.count > 0)
{
gvDenter.DataSourceID = SqlDataSourceDenter;
Response.Write("<script>alert('Denter added successfully')</script>");
InsertIntoDB.count = 0;
ClearDenterFields();
}
}
}
My aspx code is:
<asp:SqlDataSource ID="SqlDataSourceDenter" runat="server" ConnectionString="<%$ ConnectionStrings:VehiclesSystemConnectionString2 %>"
SelectCommand="SELECT [D_NIC], [D_Name], [D_Address], [D_Contact] FROM [Denters]">
</asp:SqlDataSource>
<asp:GridView ID="gvDenter" Visible="False" DataKeyNames="D_NIC" runat="server" AutoGenerateColumns="False" DataSourceID="SqlDataSourceDenter" >
</asp:GridView>
You can have something like
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
BindDataToGrid();
}
}
protected void BindDataToGrid()
{
string conString = ConfigurationManager.ConnectionStrings["MyConnectionString"].ConnectionString;
DataTable dt = new DataTable();
using (SqlConnection con = new SqlConnection(conString))
{
string myQuery = "SELECT * FROM MYTABLE";
SqlCommand cmd = new SqlCommand(myQuery);
using (SqlDataAdapter sda = new SqlDataAdapter())
{
cmd.Connection = con;
con.Open();
sda.SelectCommand = cmd;
sda.Fill(dt);
GridView1.DataSource = dt;
GridView1.DataBind();
}
}
}
protected void Add(object sender, EventArgs e)
{
//Insert To DB Code here
}

SelectedIndex auto select on page load

I have an account page where the user can view their account information.. I want them to be able to change their password here. The Way I have managed to implement it it is as follows:
Web service:
[WebMethod]
public string ChangePassword(DataSet ds)
{
string database = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=|DataDirectory|/dvd_forum.accdb;Persist Security Info=True";
OleDbConnection myConn = new OleDbConnection(database);
OleDbDataAdapter myDataAdapter = new OleDbDataAdapter("Select * from Users", myConn);
OleDbCommandBuilder builder = new OleDbCommandBuilder(myDataAdapter);
builder.QuotePrefix = "[";
builder.QuoteSuffix = "]";
myConn.Open();
myDataAdapter.Update(ds, "Users");
myConn.Close();
return "Password changed!";
}
Front code:
<asp:Label ID="username" runat="server" Text=""></asp:Label><span>'s Account</span><br />
<asp:TextBox ID="ChangePasswordInput" runat="server"></asp:TextBox>
<asp:Button ID="Button1" runat="server" Text="Save"
onclick="ChangePassword_Click" />
<asp:Label ID="Label2" runat="server" Text=""></asp:Label><asp:RequiredFieldValidator id="RequiredFieldValidator3" runat="server" ErrorMessage="Required!" ControlToValidate="ChangePasswordInput"></asp:RequiredFieldValidator>
<asp:GridView ID="GridView1" runat="server">
</asp:GridView>
back code:
public partial class Account : System.Web.UI.Page
{
public static DataSet ds;
protected void Page_Load(object sender, EventArgs e)
{
if (User.Identity.IsAuthenticated)
{
username.Text = User.Identity.Name;
}
localhost.Service1 myws = new localhost.Service1();
ds = myws.GetUserAcc(User.Identity.Name);
GridView1.DataSource = ds;
GridView1.DataBind();
}
protected void ChangePassword_Click(object sender, EventArgs e)
{
//change password
int i = GridView1.SelectedIndex;
ds.Tables["Users"].Rows[i]["password"] = ChangePasswordInput.Text;
GridView1.DataSource = ds;
GridView1.DataBind();
localhost.Service1 myws = new localhost.Service1();
Label2.Text = myws.ChangePassword(ds);
}
}
The problem with this is that I have to select the row in the gridview before changing the password. Is there any way I can have the row automatically selected as there will only ever be one row.. Or how can I code it differently to work without selecting the row first?
Thanks.
Your GridView and button are separate controls on the page, therefore you can't determine which user is selected for password change, without selecting the row in the GridView. IMO its better if you could put the button inside the GridView. Make an editable GridView.
Edit: Based on your comment that you will only have one row in your grid view, I really don't see the reason of using Gridview with datatable. You can have a label showing user name and textbox for new password. (You may wanna reconfirm the password). Then in your webservice, instead of passing datatable, you may pass the new password (its better if its encrypted) and then update the data using SQL Update statement. But if you still want to use the GridView then instead of getting the selectedIndex you can directly pass 0 in the Row index. You may check if the dataTable contains any row.
if(ds.Tables.Count > 0 && ds.Tables["Users"] != null && ds.Tables["Users"].Rows.Count > 0)
{
ds.Tables["Users"].Rows[0]["password"] = ChangePasswordInput.Text;
    GridView1.DataSource = ds;
    GridView1.DataBind();
    localhost.Service1 myws = new localhost.Service1();
    Label2.Text = myws.ChangePassword(ds);
}

Sorting GridView Formed With Data Set

The following code sample is for sorting a GridView formed With a DataSet.
Source: http://www.highoncoding.com/Articles/176_Sorting_GridView_Manually_.aspx
But it is not displaying any output.
There is no problem in sql connection.
I am unable to trace the error, please help me.
Thank You.
public partial class _Default : System.Web.UI.Page
{
private const string ASCENDING = " ASC";
private const string DESCENDING = " DESC";
private DataSet GetData()
{
SqlConnection cnn = new SqlConnection("Server=localhost;Database=Northwind;Trusted_Connection=True;");
SqlDataAdapter da = new SqlDataAdapter("SELECT TOP 5 firstname,lastname,hiredate FROM EMPLOYEES", cnn);
DataSet ds = new DataSet();
da.Fill(ds);
return ds;
}
public SortDirection GridViewSortDirection
{
get
{
if (ViewState["sortDirection"] == null)
ViewState["sortDirection"] = SortDirection.Ascending;
return (SortDirection)ViewState["sortDirection"];
}
set { ViewState["sortDirection"] = value; }
}
protected void GridView1_Sorting(object sender, GridViewSortEventArgs e)
{
string sortExpression = e.SortExpression;
if (GridViewSortDirection == SortDirection.Ascending)
{
GridViewSortDirection = SortDirection.Descending;
SortGridView(sortExpression, DESCENDING);
}
else
{
GridViewSortDirection = SortDirection.Ascending;
SortGridView(sortExpression, ASCENDING);
}
}
private void SortGridView(string sortExpression, string direction)
{
// You can cache the DataTable for improving performance
DataTable dt = GetData().Tables[0];
DataView dv = new DataView(dt);
dv.Sort = sortExpression + direction;
GridView1.DataSource = dv;
GridView1.DataBind();
}
}
aspx page
asp:GridView ID="GridView1" runat="server" AllowSorting="True" OnSorting="GridView1_Sorting">
/asp:GridView>
Problem is with Page Load event when you fill the data you add it inside if(!IsPostBack) condition .
In this article, there is explained how to sort the GridView data in ASP.NET.
GridvIew control is a powerful data grid control that allows us to display the data in tabular format with sorting and pagination. It also allows us to manipulate the data as well.
http://www.dotnetfunda.com/articles/article1598-how-to-sort-the-gridview-data-in-aspnet.aspx
//Code Behind
DataSet ds = new DataSet();
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
gvbind();
}
}
protected DataSet gvbind() // Binding the gridview using Dataset and I am using stored procedure "Proc_Displayinfo"
{
con.Open();
SqlCommand command = new SqlCommand("Proc_Displayinfo", con);
SqlDataAdapter adpt = new SqlDataAdapter(command);
DataSet ds = new DataSet();
adpt.Fill(ds);
GridView1.DataSource = ds.Tables[0];
GridView1.DataBind();
con.Close();
return ds;
}
public SortDirection dir
{
get
{
if (ViewState["dirState"] == null)
{
ViewState["dirState"] = SortDirection.Ascending;
}
return (SortDirection)ViewState["dirState"];
}
set
{
ViewState["dirState"] = value;
}
}
protected void Gridview1_Sorting(object sender, GridViewSortEventArgs e)
{
gvbind();
DataTable dt = gvbind().Tables[0];
{
string SortDir = string.Empty;
if (dir == SortDirection.Ascending)
{
dir = SortDirection.Descending;
SortDir = "Desc";
}
else
{
dir = SortDirection.Ascending;
SortDir = "Asc";
}
DataView sortedView = new DataView(dt);
sortedView.Sort = e.SortExpression + " " + SortDir;
GridView1.DataSource = sortedView;
GridView1.DataBind();
}
}
// Source Code
<asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="False" DataKeyNames="StudentId" onsorting="Gridview1_Sorting" AllowSorting="True">
<asp:TemplateField HeaderText="StudentID" SortExpression="StudentID">
<ItemTemplate>
<asp:Label ID="LBLStudentID" runat="server" Text='<%# Eval("StudentID") %>'></asp:Label>
</ItemTemplate>
<EditItemTemplate>
<asp:TextBox ID="TXTStudentID" runat="server" Text='<%# Eval("StudentID") %>'></asp:TextBox>
</EditItemTemplate>

Resources