Sorting problems in GridView and DetailsView

greenshoots
greenshoots used Ask the Experts™
on
I use a datatable to do some sorting for a GridView

dtSort.DefaultView.Sort = e.SortExpression + (string)((e.SortDirection == SortDirection.Ascending) ? " ASC" : " DESC");

Then I save the dtSort in ViewState["DataTable2"].
And then use it with the GridView. And it get sorted. Sorting works great in the GridView.

But when I set this same sorted datatable (ViewState["DataTable2"]) as DetailsViews datasource it looks like the sortorder not comes here.
Then the PageID is not the same as the rowindex in the GridView. I got the rowindex from the DataTable and not from the GridView so it should work in both GridView and DetailsView objects?

What do I miss? Looks like it works different in GridView and DetailsView?
Comment
Watch Question

Do more with

Expert Office
EXPERT OFFICE® is a registered trademark of EXPERTS EXCHANGE®

Commented:
You should never use the RowIndex for anything except referencing the physical row SLOT in the grid.

Imagine the GridView is just like an Excel spreadsheet, where the row number never changes, even if the data is sorted differently. At a certain point, the IDs might just COINCIDENTALLY line up with the row numbers, but again, that's coincidental. At any moment, the data could be sorted differently by code or by the user, and the IDs would not match up anymore:

2019-08-22_11-04-18.jpg
So what you can do here is first specify DataKeyNames in your GridView and DetailsView, like this:
https://docs.microsoft.com/en-us/dotnet/api/system.web.ui.webcontrols.gridview.datakeynames?view=netframework-4.8

<asp:GridView ID="YourGridView" DataKeyNames="PageID" ...>
   ...
</asp:GridView>

Then in your DetailsView, use SelectParameters to map to the GridView PageID:
<SelectParameters>
  <asp:ControlParameter ControlID="YourGridView" Name="PageID" />
</SelectParameters>

That should ensure that the DetailsView is linked to the PageID key of your GridView rather than trying to link on the unreliable row index.

Author

Commented:
SelectParameters you use in DataSource?
My DataSourse is a DataTable and I use no SQL. I also assign the DataTable with code not in the aspx.
Can I then use SelectParameters?

Author

Commented:
I try to use my DataTable with ObjectDataSource maybe it works... :)
Rowby Goren Makes an Impact on Screen and Online

Learn about longtime user Rowby Goren and his great contributions to the site. We explore his method for posing questions that are likely to yield a solution, and take a look at how his career transformed from a Hollywood writer to a website entrepreneur.

Author

Commented:
I think I have got it:

        public DataTable GetDataTableForObjectSource()
        {
            DataTable dt = new DataTable();
            dt.Columns.AddRange(new DataColumn[3] { new DataColumn("Id", typeof(int)),
                    new DataColumn("Name", typeof(string)),
                    new DataColumn("Country",typeof(string)) });


            dt.Rows.Add(1, "John Hammond", "United States");
            dt.Rows.Add(2, "Mudassar Khan", "India");
            dt.Rows.Add(3, "Suzanne Mathews", "France");
            dt.Rows.Add(4, "Robert Schidner", "Russia");



            if (ViewState["DataTable"] != null)
            {
                dt = (DataTable)ViewState["DataTable"];
            }
            ViewState["DataTable"] = dt;
            return dt;
        }


        private void PopulateDetailsView()
        {
            try
            {
                var objectDataSource1 =
                new ObjectDataSource(this.GetType().AssemblyQualifiedName, "GetDataTableForObjectSource") { ID = "ObjectDataSource1" };

                ControlParameter cp = new ControlParameter();
                cp.ControlID = "GridView2";
                cp.Name = "Id";

                Controls.Add(objectDataSource1);

                GridView2.DataSourceID = "ObjectDataSource1";
                GridView2.DataBind();

                DetailsView1.DataSourceID = "ObjectDataSource1";
                DetailsView1.DataBind();
            }
            catch (Exception ex_)
            {
                Debug.WriteLine(ex_.ToString());
                log.Info(ex_.ToString());
            }
        }

Author

Commented:
But when I add DataKeyNames="PageID" it does not work. Looks like it must be an existing column in the DataTable.

Commented:
Yes, it must be an existing column. You mentioned PageID in your original question so I assumed that was your key column but if it is "Id" then use that instead.

Author

Commented:
I don't understand how to take advantage of that.

Let's say I try to change the current PageID for the DetailsView when I select the row in the GridView.

protected void GridView1_SelectedIndexChanged(object sender, EventArgs e) {
                GridViewRow gwr = GridView1.Rows[GridView1.SelectedIndex];
                int Id_Index = GetColumnIndexByName(GridView1.HeaderRow, "Id");
                string Id = Convert.ToString(gwr.Cells[Id_Index].Text);
}

And then I need to check where this ID is in DetailsView and then get the corresponding PageID / RowIndex or something and then set the PageID for the DetailsView?

Or is there something smart and easier I now can do with this mapping.

Author

Commented:
Or is now my PageID in the DetailsView the same as my Controllparameter?

ControlParameter cp = new ControlParameter();
                cp.ControlID = "GridView2";
                cp.Name = "Id";

I should maybe here set ControlID="DetailsView1" according to what was said?

Author

Commented:
Or could I use more than one Controllparameter in the Objectdatasource?
I went away from using the PageID to sync my Grid and DetailsView. I now use a DataTable with only one row to represent the DetailsView. And an Objectdatasource for my Grid.

However, it was cool to use an Objectdatasource instead of a Datatable. I think I learned something new and it looks to me that sorting works simpler and better with Objectdatasource than only Datatable.

Author

Commented:
Thank you so much for your help.

Commented:
Glad to hear you found the answer. My apologies for the late response - I wasn't at my normal desk over the weekend so I didn't have a chance to test and respond before now.

Do more with

Expert Office
Submit tech questions to Ask the Experts™ at any time to receive solutions, advice, and new ideas from leading industry professionals.

Start 7-Day Free Trial