Link to home
Start Free TrialLog in
Avatar of greenshoots
greenshoots

asked on

Sorting problems in GridView and DetailsView

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?
Avatar of gr8gonzo
gr8gonzo
Flag of United States of America image

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:

User generated image
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.
Avatar of greenshoots
greenshoots

ASKER

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?
I try to use my DataTable with ObjectDataSource maybe it works... :)
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());
            }
        }
But when I add DataKeyNames="PageID" it does not work. Looks like it must be an existing column in the DataTable.
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.
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.
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?
Or could I use more than one Controllparameter in the Objectdatasource?
ASKER CERTIFIED SOLUTION
Avatar of greenshoots
greenshoots

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Thank you so much for your help.
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.