If you invert the sign of your Comparable, you'll get descending order. Depending on your exact requirements, this is usually pretty easy. Consider the following code:
public class MyController {
public Boolean sortAsc { get; set; }
public String sortField { get; set; }
// Static vars don't persist, so we use backing variables
Boolean mSortAsc;
String mSortField;
// What we display on the page
public Wrapper[] WrapperList { get; set; }
public class Wrapper implements Comparable {
// Implementation can be whatever you need
public Integer compareTo(Object other) {
Wrapper o = (Wrapper)other;
Integer baseSortValue = ...; // calculate normal value
return baseSortValue * (MyController.sortAsc? 1: -1); // Multiply by -1 to invert sort;
}
}
public void changeSort(String field) {
// Set static vars
sortAsc = mSortAsc;
sortField = mSortField;
// Set asc on field change, otherwise toggle
sortAsc = field != sortField || !sortAsc;
sortField = field;
WrapperList.sort();
// And store for next sort
mSortAsc = sortAsc;
mSortField = sortField;
}
}
I've left out some details, obviously, but this should point you in the right direction. Generally, I use apex:commandLink in the header cells to call changeSort, which takes care of all of the logic.
Edit: More Code
To sort by a column, just set the parameter for which field you wish to sort:
<apex:column >
<apex:facet name="header">
<apex:commandLink status="status" action="{!resort}" reRender="form">
<apex:param assignTo="{!newSortOrder}" value="Owner.Name" />
Assigned To {!if(sortField='Owner.Name',if(sortAsc,'▲','▼'),'')}
</apex:commandLink>
</apex:facet>
<apex:outputField value="{!record.Owner.Name}">
<apex:inlineEditSupport />
</apex:outputField>
</apex:column>
In the controller, there is a public String sortField { get; set; }
and public Boolean sortAsc { get; set; }
; the former is set by apex:param
, the latter is used by the resort
method (above called changeSort
). This particular implementation uses a SOQL ORDER BY clause, but you can use dynamic SObject methods to use the Comparable interface.
Also, see my answer on this question for how you could use an Interface to define which field is sorted (basically, you'd create a bunch of sorting interfaces, then select one to use). For example:
public compareTwo sortOrder;
public class Wrapper implements Comparable {
public Integer compareTo(Object other) {
return (sortAsc? 1: -1) * sortOrder.compare(this, (Wrapper)other);
}
}
public interface compareTwo {
Integer compare(Wrapper item1, Wrapper item2);
}
public class AccountNumberSort implements compareTwo {
public Integer compare(Wrapper item1, wrapper item2) {
return item1.AccountNumber.compareTo(item2.AccountNumber);
}
}
public class NameSort implements compareTwo {
public Integer compare(Wrapper item1, wrapper item2) {
return item1.Name.compareTo(item2.Name);
}
}
...
public void changeSort() {
sortAsc = sortField != mSortField || !sortAsc;
mSortField = sortField;
mSortAsc = sortAsc;
Map<String, Type> fieldMap = new Map<String, Type> {
'AccountNumber' => AccountNumberSort.class,
'Name' => NameSort.class
};
sortOrder = (compareTwo)fieldMap.get(sortField).newInstance();
wrapperList.sort();
}