C# .NET - Datagridview Sort selects Row - Asked By hans schlegel on 04-Mar-12 07:37 AM

Hello,

I use a datagridview with a header, it is possible to sort the rows in the dgv.
Its also possible to select rows by mouse. Normally all rows are unselected.
Now when I sort always the first (if nonselected) row is selected.
How can I prevent this behaviour?

thanks
Schlegel
D Company replied to hans schlegel on 04-Mar-12 09:54 AM
Well, u can use the Rows property of datagrid, u  can change it through coding
something like this

YourDataGridname.Rows(index).Selected = True;

//here the index is the current index, when u click on the sorting option u can also change the index for default selection


for more detail go through this http://msdn.microsoft.com/en-us/library/system.windows.forms.datagridview.selectionchanged.aspxarticle

kalpana aparnathi replied to hans schlegel on 04-Mar-12 01:13 PM


You will have to record some info that can uniquely identify the row (primary key?) in the ColumnHeaderMouseDown event and then after the sort is done find the row. You'll want to check for the DataBindingComplete event with the ListChangeType of Reset to know when the sort is complete.
hans schlegel replied to D Company on 04-Mar-12 01:47 PM
Thanks for your response, I use the Selected method in my program. I fill the datagridview, set Selected to false and no row is selected. But when I use the sort the first row always gets selected and I dont know why. My Code is ok.
Somesh Yadav replied to hans schlegel on 05-Mar-12 04:09 AM

The http://msdn.microsoft.com/en-us/library/0868ft3z%28v=vs.80%29.aspx on the DataGridView is used for a bit more simple sorting. Such as Ascending or Descending sorting and the SortOrder property is also just for "simple" sorting.

Can this behavior be implemented? Sure.

I think the easiest way to do this, is this:

  • Store the index of the first selected item
  • Take out the items that you want to sort from the DataGridView
  • Sort the list using LINQ
  • Append the two lists and add the sorted list at the index stored in the first step.

However you need to think about how you want to handle if you selecte items that are not followed by each other, for instance if you select index { 1, 3, 6, 9 } you might stil lwant to append this to index 1.

Edit

Okay so I played around with this a little bit and came up with a way that you can implement this. It's not very optimized but you'll get the idea on how I meant.

First of all this is my SortSelectedIndices-method that I use:

static IEnumerable<T> SortSelectedIndices<T>(
   
IEnumerable<T> values,
   
IEnumerable<int> selectedIndices,
   
Func<IEnumerable<T>, IEnumerable<T>> sort)
{
   
var selectedValues = new List<T>();

   
for (var i = 0; i < selectedIndices.Count(); i++)
        selectedValues
.Add(values.ElementAt(selectedIndices.ElementAt(i)));

   
var sortedList = sort(selectedValues);

   
var finalList = new List<T>();

   
var startPositionFound = false;
   
for(var i = 0; i < values.Count(); i++)
   
{
       
if (selectedIndices.Contains(i))
       
{
           
if (startPositionFound) continue;

            startPositionFound
= true;
            finalList
.AddRange(sortedList);
       
}
       
else
            finalList
.Add(values.ElementAt(i));
   
}

   
return finalList;
}

Then I call it like this:

static void Main(string[] args)
{
   
var unsorted = new[] {3, 5, 6, 1, 2, 87, 432, 23, 46, 98, 44};
   
var selected = new[] {1, 4, 7};

   
Print(unsorted);

   
var sort = new Func<IEnumerable<int>, IEnumerable<int>>(
       
(x) => x.OrderBy(y => y).ToList());

   
var sorted = SortSelectedIndices(unsorted, selected, sort);

   
Print(sorted);
}

And this prints out the following:

{ 3,5,6,1,2,87,432,23,46,98,44 }
{ 3,2,5,23,6,1,87,432,46,98,44 }

I am just using a simple method here to print this out to the console:

static void Print<T>(IEnumerable<T> values)
{
   
Console.Write("{ ");
   
Console.Write(string.Join(",", values));
   
Console.WriteLine(" }");
}

So what you can do is to have a "sort"-button, when it's pressed you invoke SortSelectedIndices and then rebind the list when you're done. Remember I have not profiled or refactored this code, it might not be as fast as you like, I just want to give you an idea on what you can do to acheive the solution.