0

I have a list of ID numbers that I pull from a session variable and convert to an Array for use in a LINQ query that will then be used to populate a dropdown list. This is basically a list of recent clients that have been accessed by the program. I would like it to show them in the order they were last accessed.

Example array values (66, 78, 55, 24, 80)

After the LINQ query, it orders them by ID by default: (24, 55, 66, 78, 80)

So when it shows in the dropdownlist it is sorted this way when all I really needed was for it to stay in the order of the array values, only reversed: (80, 24, 55, 78, 66)

Code:

// Grab pre-built session variable with comma delimited int values
string RecentClients = Session["RecentClients"].ToString();

// Convert to Array
int[] RecentClientsArray = 
Array.ConvertAll(RecentClients.Split(','), n => Convert.ToInt32(n));

// Display in gridview to see current order of array (For debug purposes)
gridArray.DataSource = RecentClientsArray;
gridArray.DataBind();

// Setup LINQ
DataClasses1DataContext db = new DataClasses1DataContext();

// Populate RecenClientList using RecentClientsArray to compare to ConsumerID
var RecentClientList = 
(from c in db.ClientNames
 where RecentClientsArray.Contains(c.ConsumerID)
 select new { FullName = c.LastName + ", " + c.FirstName + " #" + c.ConsumerID, 
              recentConsumerID = c.ConsumerID});


// Display in gridview to see new order after populating var RecentClientList 
// (for debug purposes)
gridList.DataSource = RecentClientList;
gridList.DataBind();

// Set and bind values for dropdown list.
ddLastClients.DataSource = RecentClientList;
ddLastClients.DataTextField = "FullName";
ddLastClients.DataValueField = "recentConsumerID";
ddLastClients.DataBind();

EDIT Corrected Code using accepted solution:

// Grab pre-built session variable with comma delimited int values
string RecentClients = Session["RecentClients"].ToString();

// Convert to Array
int[] RecentClientsArray = Array.ConvertAll(RecentClients.Split(','), n => Convert.ToInt32(n));

// Setup LINQ
DataClasses1DataContext db = new DataClasses1DataContext();

// Populate RecenClientList using RecentClientsArray to compare to ConsumerID
var RecentClientList = (from c in db.ClientNames
                        where RecentClientsArray.Contains(c.ConsumerID)
                        select new { FullName = c.LastName + ", " + c.FirstName + " #" + c.ConsumerID, recentConsumerID = c.ConsumerID });

var clients = (from item in RecentClientsArray
                join client in RecentClientList.ToList()
                on item equals client.recentConsumerID
                select client).Reverse().Distinct();

// Set and bind values for dropdown list.
ddLastClients.DataSource = clients;
ddLastClients.DataTextField = "FullName";
ddLastClients.DataValueField = "recentConsumerID";
ddLastClients.DataBind();

4 Answers 4

1

I would leave your queries as you have written then and then handle the ordering in memory.

Given

var RecentClientsArray = ...
var RecentClientList = ...

You can use Enumerable.Join to bring these together. Join has the property of preserving the order of the outer sequence in the join operation. Use the join to get the initial order based on the array, and then use Reverse to fulfill the final part of your requirement. So you might simply have

var clients = 
    (from item in RecentClientsArray 
     join client in RecentClientList.ToList() // materialize result from db
     on item equals client.recentConsumerID
     select client).Reverse();

You should see the clients in the reverse order of the array, and then you would use this as the datasource on your controls.

Sign up to request clarification or add additional context in comments.

2 Comments

Perfect! That did the trick. Now I just have to make sure it has a distinct so that if I click on client 66, then a few others, then back to 66, that it doesn't list them twice. EDIT: Oh.. and Thank you so much!
added .distinct() after the .Reverse() and we're in business. Thanks again. Will post finished code in original.
0

I think you need to use OrderBy(Func<>, IComparer<>) and specify your own Comparer which will implement your (copied straight from stackoverflow, sorry)... no elegant solution for its implementation yet, tho

Comments

0

Try the below, I am using List<int> because I need access to IndexOf, which I use in the added orderby clause of the LINQ query :

       List<int> RecentClientsArray = Array.ConvertAll(RecentClients.Split(','), n => Convert.ToInt32(n)).ToList();
       // other code
       var RecentClientList = (from c in db.ClientNames
                               where RecentClientsArray.Contains(c.ConsumerID)
                               orderby RecentClientsArray.IndexOf(c.ConsumerID) descending
                               select new { FullName = c.LastName + ", " + c.FirstName + " #" + c.ConsumerID, recentConsumerID = c.HorizonID });

5 Comments

Thank you for the List tip. While I get no errors in compiling, I do get an error: "Both DataSource and DataSourceID are defined on 'gridList'. Remove one definition." My gridview is defined on the .aspx page with no datasource, so not sure why this happens. If I remove the orderby it works (but still in wrong order)
Hard to debug that without being able to see the gridview opening tag and the entire code behind. You sure that you aren't setting it somewhere, Ctrl+F?
This is all that's in the tag on the aspx page: <asp:GridView ID="gridList" runat="server"></asp:GridView> And everything posted is in Page_Load and is the only code behind.
Did you change the case of RecentClientList at all? stackoverflow.com/questions/269611/…
Good item to check, but using intellisense and it keeps the case. Just doublechecked. Note, I also tried setting both the DataSourceID and DataSource for gridList to null in code behind as suggested by other users.
0

My solution: use dictionary with reverse array items.

Here is my code:

            // Grab pre-built session variable with comma delimited int values
            string RecentClients = Session["RecentClients"].ToString();

            // Convert to Array
            int[] RecentClientsArray = Array.ConvertAll(RecentClients.Split(','), n => Convert.ToInt32(n));


            //NEW- I use dictionary to get the right place in reverse
            int ind = 0;
            Dictionary<int, int> dic = new Dictionary<int, int>();
            foreach (var item in RecentClientsArray.Reverse())
            {
                dic.Add(item, ind);
                ind++;
            }


            // Display in gridview to see current order of array (For debug purposes)
            gridArray.DataSource = RecentClientsArray;
            gridArray.DataBind();

            // Setup LINQ
            DataClasses1DataContext db = new DataClasses1DataContext();

            // Populate RecenClientList using RecentClientsArray to compare to ConsumerID
            //NEW- use orderby with dictionary
            var RecentClientList = (from c in db.ClientNames
            where RecentClientsArray.Contains(c.ConsumerID)
            orderby dic[c.ConsumerID]
            select new { FullName = c.LastName + ", " + c.FirstName + " #" + c.ConsumerID, recentConsumerID = c.HorizonID, ID = c.ConsumerID });

            // Display in gridview to see new order after populating var RecentClientList (for debug purposes)
            gridList.DataSource = RecentClientList;
            gridList.DataBind();

            // Set and bind values for dropdown list.
            ddLastClients.DataSource = RecentClientList;
            ddLastClients.DataTextField = "FullName";
            ddLastClients.DataValueField = "recentConsumerID";
            ddLastClients.DataBind();           



Good Luck,

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.