Windows Develop Bookmark and Share   
 index > Windows Forms Data Controls and Databinding > DataGridView Multi-Sort Option
 

DataGridView Multi-Sort Option

Hello to All.
I'm trying to implement a multi sort option in dataGridView.
I can do it by creating a new SelectCommand and rebind it to the control, by this approach have 2 disadvantages:

1. On big database, rebind data is a heavy command, and to rebind data seem to be a waste, when I have all the data already in my DataGridView.

2. Trying to create a multi-sort dataGridView with this approach, while the select command is unknown (could be simple select * from customers or complicated-combined select, with and without Order By clause in it) won't work perfectly to all select command 
I.e.: adding the command "Order By [Field1], [Field2]" could resolved in an error when Order By already exists in the SelectCommand.

Please, anything that might help will be appreciated.

Eli

MigrationUser 1  Friday, March 25, 2005 2:22 AM
It's ok. I've manage to implement the multi-sort, using the  System.Collections.IComparer
interface, to send to DataGridView.Sort() method.

It takes 2 rows from the current datagridview, and compare each column by the selected order. it works fine.

Thanks anyway.
MigrationUser 1  Saturday, March 26, 2005 5:57 AM
That is the correct way to go! Do you mind sharing your code for your IComparer for others to learn from?

thanks!
-mark
.NET Client Program Manager
Microsoft
This post is provided "as-is"

MigrationUser 1  Tuesday, March 29, 2005 2:25 PM
This is the multi sort class:

public class MultiSortComparer : System.Collections.IComparer
{
private string[] columnNames;
private SortOrder[] columnOrder;

public MultiSortComparer(string[] columnNames, SortOrder[] columnOrder)
{
this.columnNames = columnNames;
this.columnOrder = columnOrder;
}

public int Compare(object x, object y)
{
DataGridViewRow row1 = (DataGridViewRow)x;
DataGridViewRow row2 = (DataGridViewRow)y;

// the comapre result to send in the end of the method
int compareResult = 0;
string compareColumn = "";
// the column index to compare by at wach iteration
int columnIndex = 0;
// sort will continue until compare_result != 0
bool isSortNedded = true;
while (isSortNedded)
{
compareColumn = columnNames[columnIndex];
compareResult =
Compare_Object(row1.Cells[compareColumn].Value,
   row2.Cells[compareColumn].Value);
// continue to next cell index
++columnIndex;
// if cells are equal --> continue comapre at next cell                 
// also, end of loop when there are no more column to check
isSortNedded = (compareResult == 0) &&
(columnIndex < columnNames.Length);
}
// the result is multiply by up and down settings
// dec index by one because its added before for next iteration
int sortOrderValue = 0;
if (columnOrder == null || 
columnOrder.Length <= columnIndex - 1 ||
columnOrder[columnIndex - 1] == SortOrder.None)
{
sortOrderValue = 0;
}
else
{
sortOrderValue = (columnOrder[columnIndex - 1] == SortOrder.Ascending ? 1 : -1);
}
return compareResult * sortOrderValue;
}

private int Compare_Object(object o1, object o2)
{
// object are null - equal
if (o1 == null && o2 == null) return 0;
// o1 is null o2 is not - o2 is bigger
if (o1 == null && o2 != null) return -1;
// o2 is null o1 is not - o1 is bigger
if (o1 != null && o2 == null) return 1;
// o1 and o2 is not the same type - equal
if (o1.GetType() != o2.GetType()) return 0;
// int or double or float or long
if (o1 is string)
{
string s1 = o1.ToString();
string s2 = o2.ToString();
return s1.CompareTo(s2);
}
if (o1 is DateTime)
{
DateTime d1 = (DateTime)o1;
DateTime d2 = (DateTime)o2;
return d1.CompareTo(d2);
}

if (o1 is int)
{
int n1 = (int)o1;
int n2 = (int)o2;
return (n1 > n2 ? 1 :
n1 < n2 ? -1 : 0);
}
if (o1 is bool)
{
bool b1 = (bool)o1;
bool b2 = (bool)o2;
return (b1 == b2 ? 0: b1==true ? 1 : -1);


if (o1 is float)
{
float n1 = (float)o1;
float n2 = (float)o2;
return (n1 > n2 ? 1 :
n1 < n2 ? -1 : 0);

if (o1 is double)
{
double n1 = (double)o1;
double n2 = (double)o2;
return (n1 > n2 ? 1 :
n1 < n2 ? -1 : 0);
}
if (o1 is long)
{
long n1 = (long)o1;
long n2 = (long)o2;
return (n1 > n2 ? 1 :
n1 < n2 ? -1 : 0);
}
return 0;
}
}


To use this in the DataGridView object call this method in the DataGridView:


public bool MultiSort(string[] columnNamesToSort, SortOrder[] sortOrder)
{
if (columnNamesToSort != null && columnNamesToSort.Length > 0)
{
this.Sort(new MultiSortComparer(
columnNamesToSort, sortOrder
));
return true;
}
return false;
}


Hope it helps.

Eli
MigrationUser 1  Monday, May 09, 2005 7:24 AM
To allow multi sort on a DataGridView call this method (this is a DataGridView extended object) :



/// <summary>
/// Multi sort the grid.
/// The sort order will be from 0 item on the columnNamesToSort array until 
/// the N-1 item. Sort order is used to determine ascending/descending or none
/// options. if no sort order items are set, default is acsending.
/// </summary>
/// <param name="columnNamesToSort">column names to sort, starting from item 0</param>
/// <param name="sortOrder">sorting order array matching the columns name array</param>
/// <returns></returns>
public bool MultiSort(string[] columnNamesToSort, SortOrder[] sortOrder)
{
if (columnNamesToSort != null && columnNamesToSort.Length > 0)
{
this.Sort(new MultiSortComparer(
columnNamesToSort, sortOrder
));
return true;
}
return false;
}




This is the multiSort class that I use to allow the multi sort:


public class MultiSortComparer : System.Collections.IComparer
{
private string[] columnNames;
private SortOrder[] columnOrder;

public MultiSortComparer(string[] columnNames, SortOrder[] columnOrder)
{
this.columnNames = columnNames;
this.columnOrder = columnOrder;
}

public int Compare(object x, object y)
{
DataGridViewRow row1 = (DataGridViewRow)x;
DataGridViewRow row2 = (DataGridViewRow)y;

// the comapre result to send in the end of the method
int compareResult = 0;
string compareColumn = "";
// the column index to compare by at wach iteration
int columnIndex = 0;
// sort will continue until compare_result != 0
bool isSortNedded = true;
while (isSortNedded)
{
compareColumn = columnNames[columnIndex];
compareResult =
Compare_Object(row1.Cells[compareColumn].Value,
   row2.Cells[compareColumn].Value);



// continue to next cell index
++columnIndex;
// if cells are equal --> continue comapre at next cell                 
// also, end of loop when there are no more column to check
isSortNedded = (compareResult == 0) &&
(columnIndex < columnNames.Length);
}
// the result is multiply by up and down settings
// dec index by one because its added before for next iteration
int sortOrderValue = 0;
if (columnOrder == null || 
columnOrder.Length <= columnIndex - 1 ||
columnOrder[columnIndex - 1] == SortOrder.None)
{
sortOrderValue = 0;
}
else
{
sortOrderValue = (columnOrder[columnIndex - 1] == SortOrder.Ascending ? 1 : -1);
}
return compareResult * sortOrderValue;
}

private int Compare_Object(object o1, object o2)
{
// object are null - equal
if (o1 == null && o2 == null) return 0;
// o1 is null o2 is not - o2 is bigger
if (o1 == null && o2 != null) return -1;
// o2 is null o1 is not - o1 is bigger
if (o1 != null && o2 == null) return 1;
// o1 and o2 is not the same type - equal
if (o1.GetType() != o2.GetType()) return 0;
// int or double or float or long
if (o1 is string)
{
string s1 = o1.ToString();
string s2 = o2.ToString();
return s1.CompareTo(s2);
}
if (o1 is DateTime)
{
DateTime d1 = (DateTime)o1;
DateTime d2 = (DateTime)o2;
return d1.CompareTo(d2);
}

if (o1 is int)
{
int n1 = (int)o1;
int n2 = (int)o2;
return (n1 > n2 ? 1 :
n1 < n2 ? -1 : 0);
}
if (o1 is bool)
{
bool b1 = (bool)o1;
bool b2 = (bool)o2;
return (b1 == b2 ? 0: b1==true ? 1 : -1);


if (o1 is float)
{
float n1 = (float)o1;
float n2 = (float)o2;
return (n1 > n2 ? 1 :
n1 < n2 ? -1 : 0);

if (o1 is double)
{
double n1 = (double)o1;
double n2 = (double)o2;
return (n1 > n2 ? 1 :
n1 < n2 ? -1 : 0);
}
if (o1 is long)
{
long n1 = (long)o1;
long n2 = (long)o2;
return (n1 > n2 ? 1 :
n1 < n2 ? -1 : 0);
}

return 0;



}
}



Hope it helps.

Eli
MigrationUser 1  Monday, May 09, 2005 7:44 AM
Very cool. Thanks for sharing with everyone!

-mark
Program Manager
Microsoft
This post is provided "as-is"
MigrationUser 1  Monday, May 09, 2005 4:01 PM
Or do it the lazy man's way at the binding source:

BindingSource1.Sort = "Country DESC, Address ASC";

Bryan

theBainster  Thursday, September 22, 2005 8:51 PM

You can use google to search for other answers

Custom Search

More Threads

• how to create treeview
• Questions about MSDE...
• Trouble adding new row to DataTable
• dataGridView cells problem
• UnhandledException?
• how do I save a path in access and image in a folder
• Not Visible Textbox and Binding Manager Base
• Concurrency violation happens sometimes and times not !!!!
• Inheriting from Data Source Designer
• Forcing a new new row in datagridview