Sorted gridview selects wrong row - asp.net

I have a gridview (actually a SPgridview)
And i made the columnname clickable so the users can sort the rows using the data.
And that works fine.
The problem occurs when users try to select a row after they sorted the data.
I can see that the gridview kinda "forgets" how the rows were sorted and selects the row that was at the clicked index before it got sorted..
How do i fix that?
I tried sorting the row again after the user selects a row, but that doesnt seem to work.
And should the gridview remember the fact that it was just sorted?
Thanks in advance :)

When you handle the Sorting event set a session variable set it to the sort direction and use it when you rebind your datasource.
protected void gridview_Sorting()
{
// BIND DATA Function
BindData();
DataTable dt = gridview.DataSource as DataTable;
if (dt != null)
{
//Sort the data.
dt.DefaultView.Sort = e.SortExpression + " " + GetSortDirection(e.SortExpression);
Session["sort"] = dt.DefaultView.Sort;
gridview.DataSource = dt;
gridview.DataBind();
}
}
// bind data function//
private void BindData()
{
DataTable dt = GetDataTable();
if (Session["sort"] != null)
{
//Sort the data.
dt.DefaultView.Sort = Session["sort"].ToString();
}
gridview.DataSource = dt;
gridview.DataBind();
}

Make sure that you are not rebinding the grid after a postback.
if(!IsPostBack)
{
gridView.DataSource = yourDataSource;
gridView.DataBind();
}

Are you grabbing the selected row by it's row index or by the unique identifier of the data you are wanting to edit? If you're getting by row index, it may be 'forgetting' since you are recreating the Grid on OnPostBack. Try iterating through the data and select it by it's unique ID, not its row index.

Check Johans blog regarding SPGridView and LinqDataSource

I'd made a number of sortable GridViews, but none with row command interaction before today, when I stumbled on this problem. Mine is a "plain" GridView, not SPgridview. I found this works:
In bindData(), if we have not created a DataTable and put it in the Session object, do so. Otherwise, we'll use the existing, sorted DataTable:
if (Session["dtbl"] == null) {
Session["dtbl"] = method_to_fetch_datatable();
}
gv.DataSource = Session["dtbl"] as DataTable;
gv.DataBind();
In the GridView's handling of row commands that INSERT, UPDATE or DELETE underlying data, refresh the Session object, maintaining the sort, if there is one:
Session["dtbl"] = method_to_fetch_datatable();
if (ViewState["SortExpression"] != null) {
DataTable dt = Session["dtbl"] as DataTable;
dt.DefaultView.Sort = ViewState["SortExpression"] as string;
}
bindData();

I got it working. (kinda)
In the sorting event i saved the sortexpression (the name of the column used to sort by)
and the sortdirection ascending or descending.
Then i make the datasource for the gridview and databind, and after databinding it, i use the gridview.sort command to sort by the values i saved in viewstate.
That works fine, only one problem.
When sorting i made it switch direction after pressing the same column more than one time.
Now it thinks i keep pressing the column title, so it keeps reversing the sorting.
But i tempererarely made it only sort in one direction.
And now im playing with the sender object in the sorting event, im thinking that if i could get some info about whats causing the event i could tell it to only switch direction based on the sender.
Thanks :)

Related

Rows added to gridview don't persist when save event is triggered

I have a gridview on my webpage that can have rows added dynamically. There is a for loop that adds the rows like this:
protected void AddNewJob(object sender, EventArgs e)
{
for(int i = 0; i < Convert.ToInt32(newJobCount.Text);i++)
{
TableRow tr = new TableRow();
tr.Cells.Add(ServicesDDL("-- Select Service Type --"));
tr.Cells.Add(JobsDDL("-- Select Job Type --"));
tr.Cells.Add(TextBoxCell());
tr.Cells.Add(TextBoxCell());
tr.Cells.Add(TextBoxCell());
assetTable.Rows.Add(tr);
}
}
After the rows are added and changed from their default values the rows are looped through and data is saved to the database. I'm having problems getting the rows added to the gridview to persist and exist on the gridview when the page's save event is triggered. That code looks like this:
foreach (TableRow row in assetTable.Rows)
{
if (isFirst)
{
isFirst = false;
continue;
}
DropDownList service = (DropDownList)row.Cells[0].Controls[0];
string assetText = service.SelectedItem.Value;
DropDownList jobDescription = (DropDownList)row.Cells[1].Controls[0];
string serialText = jobDescription.SelectedItem.Value;
TextBox equipmentCount = (TextBox)row.Cells[2].Controls[0];
string leaseText = equipmentCount.Text;
TextBox jobSize = (TextBox)row.Cells[3].Controls[0];
string originText = jobSize.Text;
TextBox serialNo = (TextBox)row.Cells[4].Controls[0];
string deliveryText = serialNo.Text;
string oNo = orderNo.Text;
if (assetText != "0" && serialText != "0")
{
APICallClass.Job j = new APICallClass.Job();
j.JobTypeID = Convert.ToInt32(serialText);
j.serviceID = Convert.ToInt32(assetText);
j.equipment = leaseText;
j.jobSize = originText;
j.serialNumbers = deliveryText;
j.orderID = Convert.ToInt32(global.GlobalID);
APICallClass.API.AddJob(j, Session["Variable"].ToString());
}
}
When the code pasted above runs, it only sees the rows that are pulled in from the database. I think my problem could be fixed by calling something like .databind() somewhere that I'm not, but I've tried a few places and they have not fixed the problem.
Thanks in advance for any help, and helping me become a more robust ASP.NET developer.
When a GridView is DataBind()-ed, the contents of the GridView are "rebuilt" based on the the GridView's DataSource. If you need the new row to stay in the GridView, either do not call DataBind() after the new row is added, or ensure that the contents of your new row are in the GridView's DataSource before future calls to DataBind().
In a page I wrote once I had a similar situation and did the latter. The data for the initial rows was pulled from the database on the first page load and persisted in ViewState. As the user added, removed, and reordered rows in the GridView, the page just changed the data in ViewState and re-DataBind()ed the GridView.

ASP.NET Gridview case insensitive column sorting

I am implementing a gridview to handle a single sql server database table. When I click to sort a column, it does so by capital letters first (e.g. Test, Test2, Test3, test1, test2). Is there a way to manipulate the sorting so that it would return the results as expected (e.g. Test, test1, Test2, test2, Test3)?
Try following in .aspx file:
<asp:GridView ID="grd" runat="server">
</asp:GridView>
And add below in .aspx.cs:
protected void Page_Load(object sender, EventArgs e)
{
DataTable dt = new DataTable();
dt.Columns.Add("Subject", typeof(string));
dt.Rows.Add("Test");
dt.Rows.Add("Test2");
dt.Rows.Add("Test3");
dt.Rows.Add("test1");
dt.Rows.Add("test2");
dt.CaseSensitive = true; // this will allow case sensitive sorting
dt.DefaultView.Sort = "Subject asc";
grd.DataSource = dt;
grd.DataBind();
}
For more details refer this link How to sort a DataView in a case-insensitive manner?
Please mark this answer useful if this solve your problem.
I think you have to use the Grid's Sorting event to do a custom sort:
http://www.nullskull.com/a/866/aspnet--sorting-a-gridview-bound-to-a-custom-data-object.aspx
Otherwise if you don't want to do that, just have the database return another column with all lowercase text. Then in the gridView Column, where you have the current Test, Test2,etc...display both in there, have one be a hidden label and set the sort to that column. I haven't tried this but it might work, so in that's columns ItemTemplate have both output but only show one, then sort on the hidden one.

How to bind data column to textbox?

I have datagridview and textboxes on form. I load records from different tables when user clicks any one radiobutton. Data in grid is shown perfectly. I want to show values of the row in those textboxes.
One solution can be: binding data from dataset.
Second one can be: transfer values of each cell of row to respective textbox.
Please help me. And, please tell me which one is better or is there any other method which is even better than these two.
Thanks in advance.
Try using a BindingSource
BindingSource bindingSource = new BindingSource();
DataSet dataSet = new DataSet();
DataAdapter da1 = new DataAdapter("Select * from Customers", conn1);
DataAdapter da2 = new DataAdapter("Select * form Orders", conn1);
da1.Fill(dataSet,"Customers");
da2.Fill(dataSet,"Orders");
//Let we set Customers table as bindiningSource datasource
bindingSource.DataSource = dataSet.Tables["Customers"];
private void RadioButtonCustomers_CheckedChanged(object sender, EventArgs e)
{
if(radioButtonCustomers.Checked==true)
bindingSource.DataSource =dataSet.Tables["Customers"];
}
private void RadioButtonOrders_CheckedChanged(object sender, EventArgs e)
{
if(radioButtonOrders.Checked==true)
bindingSource.DataSource = dataSet.Tables["Orders"];
}
//First param of Binding is to which prop of TextBox to bind the value
//Second param is the data source
//Third param is the data member or the column name of the table as datasource, so
//we have to get that table from casting the bindingSource datasource prop and casting it
//to DataTable obj and after that to take the ColumnName prop of the desired column
textBox1.DataBindings.Add(new Binding("Text",bindingSource,((DataTable)bindingSource.DataSource).Columns[0].ColumnName));
textBox2.DataBindings.Add(new Binding("Text",bindingSource,((DataTable)bindingSource.DataSource).Columns[1].ColumnName));
etc...
Even if you change the datasource prop of bindingSource, textboxes will remain binded to rowvalue of first and second column
Hope this help.
Sir I done it making a simple WindowsForm with 2 radio buttons, 2 textboxes and datagridview
here is the sln file http://www13.zippyshare.com/v/98590888/file.html this must help u.
I tried many options to display value in textbox on the same form, but it was not working as datagridview could display records of two different tables.
Instead, I used the following event of datagridview:
private void dataGridView1_CellMouseClick(object sender, DataGridViewCellMouseEventArgs e)
{
this.dataGridView1.SelectionChanged += new System.EventHandler(this.DisplayValueinTextBox);
}
In DisplayValueinTextBox, I wrote following code based on numbers of columns displayed for each table:
private void DisplayValueinTextBox(object sender, EventArgs e)
{
try
{
textBox1.Text = dataGridView1.SelectedCells[0].Value.ToString();
textBox2.Text = dataGridView1.SelectedCells[1].Value.ToString();
textBox3.Text = dataGridView1.SelectedCells[2].Value.ToString();
if (tblGrid == "Employee") //name of table which has more columns in grid
{
textBox4.Text = dataGridView1.SelectedCells[3].Value.ToString();
textBox5.Text = dataGridView1.SelectedCells[4].Value.ToString();
textBox6.Text = dataGridView1.SelectedCells[5].Value.ToString();
}
this.dataGridView1.SelectionChanged -= new System.EventHandler(this.DisplayValueinTextBox); //removed it as I was getting error.
}
catch (Exception exdisp)
{
MessageBox.Show(exdisp.Message);
}
}
I also changed SelectionMode property of dataGridView to FullRowSelect. This will ensure that textbox1 is displaying value of SelectedCells[0] even if user clicks any cell.
I still hope there is even a better option, so I wait for comments on this.

GridView as DataTable source sorts only for the first time

I implemented sorting on my GridView with a DataTable as DataSource by using code from this MSDN link. However, my grid sorts for the first time when I click any column, and after that it does not sort on clicking any other column.
Code in the PageLoad() event -
if (!Page.IsPostBack)
{
HView hv = new HView ();
DataTable HTable = new DataTable("hTable");
HTable = hv.FillTable();
Session["hTable"] = HTable;
GridView2.DataSource = Session["hTable"];
GridView2.DataBind();
}
Code in the Sorting event -
protected void GridView2_Sorting(object sender, GridViewSortEventArgs e)
{
DataTable notesDT = Session["hTable"] as DataTable;
if (notesDT != null)
{
notesDT.DefaultView.Sort = e.SortExpression + " " + GetSortDirection(e.SortDirection);
GridView2.DataSource = Session["hTable"];
GridView2.DataBind();
}
}
Does anybody have an idea of what I may be doing wrong?
EDIT: I just realized this. If I select a particular row, I have another view that gets populated with details about that row. When I view some rows details first before trying to sort any columns, then sorting works perfectly fine, any number of times. However, if I try to sort before selecting a row, it works only once.
You are using the DataTable as DataSource in the sorting event, but you should use the sorted view instead. Sorting the view won't change the sort order of the data in the table, just the order in the view.
protected void GridView2_Sorting(object sender, GridViewSortEventArgs e)
{
DataTable notesDT = Session["hTable"] as DataTable;
if (notesDT != null)
{
notesDT.DefaultView.Sort = e.SortExpression + " " + GetSortDirection(e.SortDirection);
GridView2.DataSource = notesDT.DefaultView;
GridView2.DataBind();
}
}
Edit: Although that i've just noticed that you're using rhe same code from MSDN.
You could also try to create a new DataTable from the view:
GridView2.DataSource = notesDT.DefaultView.ToTable(true);
You don't need stored the data table into a session. Actually putting the entire data table into session is not a good idea at all. Any particular reason for that?

How do I sort my datagrid?

Editing some legacy code that populates a datagrid entirely in code. I need to order it by two columns but I don't know how. Which event do I hook into and what can I do to order the 2nd and 3rd columns (that contain dates) in order of most recent first?
Edit: Argh it's a datagrid
Datagrid or GridView?
you can create a dataview and sort it (in the constuctor) then bind this back to the grid in the "sorting" event
something like this might be what you're after
protected void myGridView_Sorting(object sender, GridViewSortEventArgs e)
{
// Your data
DataTable dt = new DataTable();
// Create the view
DataView dv = new DataView(dt, "", "COLUMN_TO_SORT", DataViewRowState.CurrentRows);
// Rebind
myGridView.DataSource = dt;
myGridView.DataBind();
}

Resources