This is a migrated thread and some comments may be shown as answers.

RadGrid - Finding and selecting a row

6 Answers 877 Views
General Discussions
This is a migrated thread and some comments may be shown as answers.
Brad
Top achievements
Rank 1
Brad asked on 19 Aug 2011, 03:06 AM

In our application, we need to be able to return to the page with the grid, and have the grid select the row you were on before you left.

The path I have been approaching this issue from was to store the PageNumber, the ItemIndex and the NumberPerPage whenever you select a row, in session. Then the user could leave the page and when they return I could simply look for those values and set the grid accordingly. This almost worked.

The problem was that one of the things they user could do when away from the page was change data that the grid is showing. For example, my grid lists Locations is sorted by the Location's Trading Name.

If they select the first row in the grid ('ACME'), then leave that page and in another part of the site and change the Trading Name of that location to 'Z-Acme', returning the grid, the wrong row will be selected. Furthermore, it will most likely be on the wrong page.

What I need is a concrete way to store some value, and to have the grid find and select the correct row based on that value.Regardless of where that row is now.  No matter what page or item index.

I did this code (hardcoded for now) but this only finds the row if it is in the currently loaded set.
protected void rgLocations_DataBound(object sender, EventArgs e)
        {
            string SBingo = String.Empty;
 
            for(int i = 0; i < rgLocations.Items.Count; i++)
            {
                if (rgLocations.Items[i]["Trading_Name"].Text == "Z-Acme")
                {
                    SBingo = "Found it";
                }
            }
        }

This is not ideal for a couple of reasons.

1. As mentioned above it only searches the records currently returned (which might be just 10 records out of a set of 1000s)

2. The search criteria is based on the Trading Name. As two or more locations 'might' have the same Trading Name in my app, this is far from ideal. I'd like this based on the Primary Key ID of each row. Note: the Primary key is not displayed in the grid. Can the RadGrid store but not display the primary key from each row?

What I'd like is some generic function that takes 2 parameters.
 
SetGrid(ref RadGrid r, int ItemID)

I just pass it the grid I want to set and the item ID of the row I want selected.

This code would need to happen before the grid is bound to the data source I would think. But I'm not sure.

Problem is I can't see how to do this. The RadGrid seems to work in blocks of data that are 'PageSize' in size.

Anyone done something similar? This seems like pretty basic stuff that should be part of the RadGrid. Maybe I'm just missing it.

Brad
















6 Answers, 1 is accepted

Sort by
0
Rory
Top achievements
Rank 1
answered on 19 Aug 2011, 07:37 PM
Hi Brad,
Here is how I do it in the clientside code of course we don't change the page like we probably should but you get the idearr. I imagine you could also use the DataKeyValue in your serverside code too.

function  ReSelectRow()   
            {   
                var Rows = $find("<%=RadGridContact.ClientID %>").get_masterTableView().get_dataItems();  
                for (var i = 0; i < Rows.length; i++)  
                {  
                    var row = Rows[i];  
                    if(row.getDataKeyValue("ContactID") == selectedContactID)  
                        row.set_selected(true); 
                
            }


<telerik:RadAjaxManager EnablePageHeadUpdate="true" ID="Rap1" runat="server" ClientEvents-OnResponseEnd="DisplayMessages;ReSelectRow" EnableAJAX="true" EnableEmbeddedScripts="true" EnableTheming="true">


0
Brad
Top achievements
Rank 1
answered on 22 Aug 2011, 12:02 AM
Rory

Thanks for your client side idea but like you said, it does not change the page.

I need to have the correct page and row selected. There is every chance that when my users return the page, the data in the RadGrid will be displayed in a different order such that I can't rely on the previous ItemIndex etc.

Here the example in point form

1. We have a location called 'Acme' and it is listed in the 3rd row of the first page of result, just after 'Aaron's Ant Farms' and 'ABC'.

2. The user selects the 'Acme' row. This changes the contents of 7 child grids below displayed in tabs. Then if the user hits a button on the page they are taken to a different page where 'Acme' is the 'selected Location'. One of things they 'may 'do when in 'Acme' mode on this new page is change it's name. So imagine they change 'Acme' to 'Z-Acme'.

3. Now when they return to the first page with the RadGrid and I need to have the now Z-Acme row selected.

But alas it is not on the first page of results to be selected.

I need it selected.

I have and idea of how I might do it. But I'm not sure yet if it will work.  The idea I have it do make an extra call to the db before the grid is bound, to select a full set of Locations, find at what position Z-Acme is in the returned set.

Then I could do some simple maths to calculate the PageNumber and ItemIndex to set the grid to based on the current PageSize.

For example, Imaging the Z-Acme is now the 45th location in the full set of locations and the current PageSize is set to 10.

In psydocode.

PageNumber = (int) FullItemIndex / NumberPerPage
ItemIndex = FullItemIndex % NumberPerPage

This would almost work, but adds another db call and a function to loop the result set to find the matching Location.

I'd have to keep in mind that a Location name 'might' be shared by 1 or more locations, so I'd need to have the original location's ID stored and match that too. 

Before I head down this path I'm hoping the RadGrid has a better way to do this.

Brad











0
Brad
Top achievements
Rank 1
answered on 22 Aug 2011, 07:49 AM
Ok. Looks like  I might have this sussed. The only problem now is I can't get the radgrid to show the right page or highlight right item index.

Here is my code.

private void Page_Init(object sender, System.EventArgs e)
 {
 
     Location loc = new Location();
     DataTable dt = loc.GetLocationsForRadGridSetting(User_ID);
 
     int CurrentLocationID = Convert.ToInt32(HttpContext.Current.Session["CurrentLocationID"]);
 
     if (CurrentLocationID > 0)
     {
         int iIndex = 0;
         int FullItemIndex = 0;
         foreach (DataRow dr in dt.Rows)
         {
             if (CurrentLocationID == Convert.ToInt32(dr["loc_Location_ID"].ToString()))
             {
                 FullItemIndex = iIndex;
             }
             iIndex++;
         }
 
         int PageSize = rgLocations.PageSize;
         int PageNumber = FullItemIndex / PageSize;
         int ItemIndex = FullItemIndex % PageSize;
 
         rgLocations.CurrentPageIndex = PageNumber;
 
         int[] iItemIndexes;
         iItemIndexes = new int[1];
         iItemIndexes[0] = ItemIndex;
         rgLocations.SelectedIndexes.Add(iItemIndexes);
          
     }
     
    // Set the DataSource for the grid here
     dsLocations.SelectCommand = "select * from GetLocations WHERE loc_User_ID = " + User_ID.ToString() + " ORDER BY loc_Trading_Name ASC";

I even tried setting the grids datasource selectCommand at the top of the code block above. That did not work either..

How can I get the grid to set itself to the PageNumber and ItemIndex of my choosing? Is Page_Init the wrong place to do this?

0
Accepted
Rory
Top achievements
Rank 1
answered on 22 Aug 2011, 05:28 PM
Hey Brad,
Yea try setting your grid's page index in the grid_NeedDataSource event. Then set your selected indexes in your page's prerender event. This seems to work for me using your code.
0
Brad
Top achievements
Rank 1
answered on 25 Aug 2011, 06:15 AM
I got this sorted in the end with the little bit of Rory's solution (which was not exactly how I did it in the end, but it did lead me in the right direction) and a little of my own work due to the details of my project.

Just to recap, I have a grid that has 6 child grids. Each grid has an edit option for whichever row on that grid you have selected. Each edit option takes the user away from this page to a another page where all sorts of stuff can happen. Not the least of which was the example above, were the Trading Name could be edited making a return to the grid page tricky to reset the originally selected row.

Here is how I solved it.

First, when you click a row I called the <grid>_OnItemCommand event to set a session variable with the selected row Primary Key ID.

This ID I extracted from the grid SqlDataSource. Check it out in this rgLocations example.

        protected void rgLocations_ItemCommand(object sender, GridCommandEventArgs e)
        {
            SetSessionID(ref dsLocations, ref rgLocations, "loc_Location_ID");
        }
 
 
private void SetSessionID(ref SqlDataSource ds, ref RadGrid rg, string PrimaryKey)
        {
            int ItemIndex;
            int PageIndex = rg.CurrentPageIndex;
            if (rg.SelectedIndexes.Count > 0)
                ItemIndex = Convert.ToInt32(rg.SelectedIndexes[0]);
            else
                ItemIndex = 0;
            int PageSize = rg.PageSize;
 
            int FullItemIndex = PageIndex * PageSize + ItemIndex;
            DataView dv = (DataView)ds.Select(DataSourceSelectArguments.Empty);
            Session[PrimaryKey] = Convert.ToInt32(dv.Table.Rows[FullItemIndex][PrimaryKey]);
        }

Note I have made the SetSessionID method generic enough to but used to work with all of my grids.

For example, on one of the child grids called rgNotes, it's OnItemCommand looks like this.

protected void rgNotes_OnItemCommand(object sender, GridCommandEventArgs e)
        {
            SetSessionID(ref dsNotes, ref rgNotes, "not_Note_ID");
        }

Neat and effective, this creates for me session variables like Session["loc_Location_ID"] and Session["not_Note_ID"]. No matter where I am in the site now, I know which Location, Note, Activity, Address etc etc they had selected on this page. Cool.

Next, when they return to this page, I need to find and select the correct row AND page for each grid.

That is done in the rgLocations_PreRender event where I call a method called 'SetGrids()'. 

        private void SetGrids()
        {
            SetIndexAndPageNumber(ref dsLocations, ref rgLocations, "loc_Location_ID");
            SetIndexAndPageNumber(ref dsNotes, ref rgNotes, "not_Note_ID");
            SetIndexAndPageNumber(ref dsActivities, ref rgActivities, "act_Activity_ID");
            SetIndexAndPageNumber(ref dsProspects, ref rgProspects, "pro_Prospect_ID");
            SetIndexAndPageNumber(ref dsContacts, ref rgContacts, "con_Contact_ID");
            SetIndexAndPageNumber(ref dsAddresses, ref rgAddresses, "add_Address_ID");
        }
 
 private void SetIndexAndPageNumber(ref SqlDataSource ds, ref RadGrid rg, string PrimaryKey)
        {
            int CurrentID = Convert.ToInt32(Session[PrimaryKey]);
 
            if (CurrentID > 0)
            {
                DataView dv = (DataView)ds.Select(DataSourceSelectArguments.Empty);
                int FullItemIndex = 0;
 
                int i = 0;
                foreach (DataRow dr in dv.Table.Rows)
                {
                    if (CurrentID == Convert.ToInt32(dr[PrimaryKey]))
                    {
                        FullItemIndex = i;
                        break;
                    }
                    i++;
                }
 
 
                int PageSize = rg.PageSize;
                int PageNumber = FullItemIndex / PageSize;
                int ItemIndex = FullItemIndex % PageSize;
 
                rg.CurrentPageIndex = PageNumber;
                rg.Rebind();
 
                iItemIndexes = new int[1];
                iItemIndexes[0] = ItemIndex;
 
                rg.SelectedIndexes.Clear();
                rg.SelectedIndexes.Add(iItemIndexes);
            }
        }


And Voilâ. All of the grids get whatever row you had selected before, selected.

Note I am looping though the SqlDataSource to find the matching ID. That is great for finding where an item is now regardless of how it's values might have been changed out in the site. (like the Trading Name of my Location changing) Furthermore, I have situations where the one that should be selected back on this page might change elsewhere on the site. Simple, just change it's Session[PrimaryKey] value. This code with select the correct one regardless. 

One thing I'm not sure about yet, is if 'Sorting' of the grids will effect my code. I've not done sorting yet. Will the SqlDataSource be in the sorted order or do I need to sort it myself to match that of each grid? I'll find out soon enough. Sorting is next.

Brad















0
Brad
Top achievements
Rank 1
answered on 25 Aug 2011, 06:28 AM
I forgot to mention one Got'cha that had me messed up for a bit was.....

If you need to set the page index of your grid, you need to set it, then rebind the grid.

However, you don't need to rebind the grid after setting it's SelectedIndexes value. 

Sounds simple enough now, but had me pulling my hair out for a while there where I was not rebinding, then rebinding after setting both values, trying the code in page_PreRender, then rgLocations_ItemCommand, then, rgLocations_PreRender, then goodness knows where else I tried setting the page index.

You can see it in  my code above.

rg.CurrentPageIndex = PageNumber;
rg.Rebind();

Do this, then set your selected row.


Tags
General Discussions
Asked by
Brad
Top achievements
Rank 1
Answers by
Rory
Top achievements
Rank 1
Brad
Top achievements
Rank 1
Share this question
or