Document directory
- IComparable <T> Interface
- IComparer <T> Interface
- Implement the IComparer <T> Interface
- Page call
Code download: http://www.tracefact.net/sourcecode/filterSorting.rar
Introduction to sorting based on Business Objects
In the previous article, based on the filtering of business objects, we discussed how to implement Predicate <T> (T object) delegation and customize the DateFilter class to filter business objects. Like filtering, sorting is also a common and important operation. When sorting Business Objects, ObjectDataSource cannot be used as the data source, because it only supports automatic sorting for DataView, able, and DataSet. However, you can still compile a Sorting event processing method for the GridView. By assembling an SQL statement, you can use the "Order By" clause to complete Sorting.
Like filtering, If We cache business objects on the server, we extract data from the database during the first visit and then cache the data, subsequent requests only target cached Business Objects, which can reduce database dependencies and improve efficiency. This article will discuss how to sort the obtained business objects, including simple sorting, sorting by any column, and composite sorting by multiple columns.
NOTE: This article is written in the previous article. I will not describe some repeated content in this article. We recommend that you read the filtering based on Business Objects first.
Simple sorting-default sorting of fixed attributes
Different from the previous article, I will not describe how to use assembled SQL to sort objects. We will look at sorting objects based on List <Order>. We know that List <T> provides the Sort () method for sorting operations. How can it be used? First, create an ObjSort. aspx file, and add the following code to the Code:
Protected void Page_Load (object sender, EventArgs e)
{
Label lb1 = new Label ();
List <int> list = new List <int> ();
List. Add (4 );
List. Add (5 );
List. Add (2 );
List. Add (9 );
List. Add (1 );
Foreach (int item in list ){
Lb1.Text + = item. ToString () + ",";
}
Form1.Controls. Add (lb1 );
HtmlGenericControl hr = new HtmlGenericControl ("hr ");
Form1.Controls. Add (hr );
Label lb2 = new Label ();
List. Sort (); // Sort the list
Foreach (int item in list ){
Lb2.Text + = item. ToString () + ",";
}
Form1.Controls. Add (lb2 );
}
You can see that the elements in the List are sorted by using the Sort () method on the List <int>. Now we are at OrderManager. in cs, add a new method GetSortList (), which is used to obtain List objects. Because the GetList () method returns too many records, we only focus on Sorting in this article, therefore, we only return 15 records.
// Obtain the list for sorting
Public static List <Order> GetSortList (){
List <Order> list = HttpContext. Current. Cache ["sortList"] as List <Order>;
If (list = null ){
List = GetList ("Select Top 15 OrderId, CustomerId, ShipCountry, OrderDate From Orders ");
HttpContext. Current. Cache. Insert ("sortList", list );
}
Return list;
}
If you have not read the previous article, you only need to know that this method returns a List <Order> type business object, representing an Order List. (The Order object contains four common attributes, orderId, mermerid, OrderDate, Country ). Then we create the ObjSort2.aspx file, drag and drop a Reperter control on it, and write some code to display a table:
<Asp: Repeater runat = "server" ID = "rpOrderList">
<HeaderTemplate>
<Table>
<Tr>
<Th>
<Asp: LinkButton ID = "lbtOrderId" runat = "server"> OrderId </asp: LinkButton>
</Th>
<Th>
<Asp: LinkButton ID = "lbtCustomerId" runat = "server"> CustomerId </asp: LinkButton>
</Th>
<Th>
<Asp: LinkButton ID = "lbtOrderDate" runat = "server"> OrderDate </asp: LinkButton>
</Th>
<Th>
<Asp: LinkButton ID = "lbtCountry" runat = "server"> Country </asp: LinkButton>
</Th>
</Tr>
</HeaderTemplate>
<ItemTemplate>
<Tr>
<Td> <% # Eval ("OrderId") %> </td>
<Td> <% # Eval ("CustomerId") %> </td>
<Td> <% # Eval ("OrderDate") %> </td>
<Td> <% # Eval ("Country") %> </td>
</Tr>
</ItemTemplate>
<FooterTemplate>
</Table>
</FooterTemplate>
</Asp: Repeater>
Then, in the Page_Load event of the post code ObjSort2.aspx. cs, add the following two rows:
RpOrderList. DataSource = OrderManager. GetSortList ();
RpOrderList. DataBind ();
Then open the page and you can see that the list is output on the page. Now we want to sort the List, and we will modify the above Code following the List <int> practice:
List <Order> list = OrderManager. GetSortList ();
List. Sort (); // It is expected to be sorted.
RpOrderList. DataSource = list;
RpOrderList. DataBind ();
In fact, we will get an error: there must be at least one object to implement IComparable.
IComparable <T> Interface
We just want to know why an error occurs: The Order object contains four attributes: OrderId, CustomerId, OrderDate, and Country, and the int value only has its own value, when we call Sort () on List <Order>, the List objects do not know how to Sort or which attribute to Sort. The IComparable interface defines the sorting rules. If we want to sort the List <Order> object, we need to make the List element, that is, the Order object implements this interface. In fact, the reason why List <int> can directly call the Sort () method is that int and almost all basic types (such as string, char, datetime, etc ), IComparable <T>.
Public interface IComparable <T> {
Int CompareTo (T other );
}
This interface only needs to implement one method, CompareTo (), which transmits another object of the same type as the object to be compared (the current object in the list) and returns a value of the int type: the current object is smaller than zero than the other parameter. Zero is equal to other. The current object is greater than zero than other.
Now let the Order object (see the downloaded code for Order) implement this interface:
// Implement the IComparable <T> Interface
Public int CompareTo (Order other ){
Return this. CustomerId. CompareTo (other. CustomerId );
}
We delegate the sorting rule to CustomerId for processing, because CustomerId is a string type and its CompareTo () method is called. In this way, when you call Sort () on List <Order>, the rules defined here are sorted by mermerid. Open ObjSort. aspx again, and you can see that the list is sorted by CustomerId.
Advanced sorting-combined sorting of multiple attributes IComparer <T> Interface
The above only provides a default sorting for the list. In fact, we often need to sort multiple columns, and we also need to sort them in descending or ascending order, we even want to sort the combination of multiple columns. For example, we first sort the CustomerId in ascending order and then sort the OrderDate in descending order. At this time, although CompareTo (Order other) can also be used, but to add additional fields or attributes to the Order object, these. net Framewok has been taken into account, and the IComparer <T> interface is provided to encapsulate sorting rules. We can implement this interface to complete sorting.
Public interface IComparer <T> {
Int Compare (T x, T y );
}
IComparer <T> only implements one method. Compare () accepts two parameters of the same type and returns the result of the int type, similar to IComparable <T>, when the return value is less than 0, x is less than y; when x is equal to 0, x is equal to y; when x is greater than 0, x is greater than y. Note that this interface does not require us to implement the Order object, but requires another object to implement it, such as OrderComparer. When we call the Sort () method, pass it as a parameter. This OrderComparer is only used to sort Order objects and cannot be applied to other objects. Therefore, we declare it as an Order nested class.
Implement the IComparer <T> Interface
Open the Order. cs file and modify it as follows. First, add an enumeration SortDirection to indicate the direction of sorting:
// Reusable enumeration, indicating the direction of sorting
Public enum SortDirection {
Ascending = 0,
Descending
}
Add an enumeration inside the Order class. This enumeration type represents the attributes that can be sorted:
// Nested enumeration, which applies only to this business object and can be sorted.
Public enum SortField {
OrderId,
CustomerId,
OrderDate,
Country
}
We also need to define another Sorter structure, which contains two fields, one SortDirection type and one SortField type, which encapsulates the necessary information for sorting: which attribute is sorted in ascending or descending order. Since this structure is still only for the Order object, we still define it inside the Order:
// Nested structure, which applies only to this business object and the sorting attributes and Methods
Public struct Sorter {
Public SortField field;
Public SortDirection direction;
Public Sorter (SortField field, SortDirection direction ){
This. field = field;
This. direction = direction;
}
Public Sorter (SortField field ){
This. field = field;
This. direction = SortDirection. Ascending;
}
}
Next, we define the class OrderComparer that implements IComparer <T> in Order:
// Nested class, which only sorts the Business Objects
Public class OrderComparer: IComparer <Order> {
}
Now let's consider how to implement it: because we want to sort an attribute in a certain way, we should at least pass these two parameters in, therefore, OrderCompare should contain fields to maintain SortDirection and SortField; because we expect that we can sort multiple attributes in combination, we should maintain a list of them, while SortDirection and SortFiled, it is already included in the Sorter structure, so it only needs to maintain a List <Sorter> structure:
Public class OrderComparer: IComparer <Order> {
Private List <Sorter> list;
// Constructor, set the sorting Field List
Public OrderComparer (List <Sorter> list ){
This. list = list;
}
}
Next, we will consider how to sort the attributes. First, we will start with a simple process. We will not consider how to sort multiple attributes, but simply sort a certain attribute in a certain way. Then we need to add a method CompareTo (), it accepts the sorting attributes, sorting methods, and sorting objects, and finally returns the int type, indicating the size (Location Order) of the two objects ):
// Sort a single attribute in a certain way
Public int Compare (Order x, Order y, SortField field, SortDirection direction ){
Int result = 0; // The default sorting position does not change.
Switch (field ){
Case SortField. Country:
If (direction = SortDirection. Ascending)
Result = x. Country. CompareTo (y. Country );
Else
Result = y. Country. CompareTo (x. Country );
Break;
Case SortField. CustomerId:
If (direction = SortDirection. Ascending)
Result = x. CustomerId. CompareTo (y. CustomerId );
Else
Result = y. CustomerId. CompareTo (x. CustomerId );
Break;
Case SortField. OrderDate:
If (direction = SortDirection. Ascending)
Result = x. OrderDate. CompareTo (y. OrderDate );
Else
Result = y. OrderDate. CompareTo (x. OrderDate );
Break;
Case SortField. OrderId:
If (direction = SortDirection. Ascending)
Result = x. OrderId. CompareTo (y. OrderId );
Else
Result = y. OrderId. CompareTo (x. OrderId );
Break;
}
Return result;
}
However, this method does not implement the IComparer <T> interface, nor can it sort multiple columns. Before proceeding, we will consider how to sort multiple attributes (such as A, B, and C) of two objects: Compare attribute A first. If attribute A is the same, continue to compare property B. If property B is the same, continue to compare property C. In this process, as long as any attribute is different, the order of the two objects can be determined, that is, the subsequent attribute comparison is not performed.
With the idea, we now implement the IComparer <T> interface and write the method.
// Implement the IComparer Interface
Public int Compare (Order x, Order y ){
Int result = 0;
Foreach (Sorter item in list ){
Result = Compare (x, y, item. field, item. direction );
If (result! = 0) // once the result is not 0, the location is split and the cycle exists.
Break;
}
Return result;
}
In this method, we traverse the List <Sorter> and call the comparison method Compare (Order x, Order y, sortField field, SortDirection ction). Once the comparison result is not 0, the loop jumps out.
Well, the implementation of the OrderComparer class has been completed. Let's take a look at what else can be done: If you need to create a list first every time you call Sort for sorting, specifying a sorting rule to construct an OrderCompare object is obviously troublesome. Therefore, we add a set of overloaded methods to the Book class, GetComparer (), to simplify the operation steps for future calls:
// Specify the sorting attribute and sorting method
Public static OrderComparer GetComparer (SortField field, SortDirection direction ){
List <Sorter> list = new List <Sorter> ();
Sorter sorter = new Sorter (field, direction );
List. Add (sorter );
Return new OrderComparer (list );
}
// Specify the sorting attribute. The default value is ascending.
Public static OrderComparer GetComparer (SortField field ){
Return new OrderComparer (field, SortDirection. Ascending );
}
// The OrderId is sorted in ascending order by default.
Public static OrderComparer GetComparer (){
Return new OrderComparer (SortField. OrderId, SortDirection. Ascending );
}
// Sort the list
Public static OrderComparer GetComparer (List <Sorter> list ){
Return new OrderComparer (list );
}
Now, the OrderComparer class is all created. Let's take a look at how to use it:
Page call
Let's modify the post-code file to see how to set it. We will change Sort () to this:
List. Sort (Order. GetComparer (Order. SortField. Country, SortDirection. Descending); // Sort by Country in reverse Order
Then, view the page and find that the list is sorted in reverse order by the Country attribute. So what if we want to sort by Country in reverse order and then by mermerid?
// Sort by Country in descending order and CustomerId in ascending order
List <Order. Sorter> sorterList = new List <Order. Sorter> (); // create a sorterList first
SorterList. Add (new Order. Sorter (Order. SortField. Country, SortDirection. Descending); // sort by Country Desc first
SorterList. Add (new Order. Sorter (Order. SortField. CustomerId); // use CustomerId Asc
List. Sort (Order. GetComparer (sorterList ));
Now on the page, we can see that the list is sorted as expected. In this article, we directly write the SortList for sorting in the Code for demonstration purposes only. In fact, these should be dynamically created based on user selection. On the ObjSort2.aspx page, I used the LinkButton for the table title. If you are interested, you can write the Click Event of the LinkButton to dynamically implement this sorting process.
Summary
This article discusses in detail how to sort the list (Business Objects.
First, we understand the IComparable <T> interface, and learn how to implement this interface to implement a default sorting for a certain field. Next, we will discuss in detail how to sort any single attribute and multiple attribute combinations by implementing an IComparer <T> interface.
As you can see, once you have mastered the method, writing code such as OrderComparer is boring, later, let's take a look at how to use reflection to compile a small program to automatically generate the code for us.
Thank you for reading this article. I hope this article will help you.