I'm implementing paging using CamlQuery and ListItemCollection, sorting results by the name field. I would like folders to come first, as they do in UI, e.g. "folder A2, folder B2, file A1, file B1", but instead I get "file A1, folder A2, file B1, folder B2".
What is the best way to accomplish such sorting and paging? Note that for paging I have to specify the value of the sorting field which will be the first record of the page – I've considered adding two sorting fields into CAML, but I'm not sure whether I can use two fields in ListItemCollectionPosition.PagingInfo.
The code I'm currently using is like this:
var queryText = @"
<View>
<Query>
<OrderBy Override='TRUE'>
<FieldRef Name='FileLeafRef' Ascending='True' />
</OrderBy>
</Query>
...
<RowLimit>
10
</RowLimit>
</View>";
var camlQuery = new CamlQuery();
camlQuery.ViewXml = queryText;
camlQuery.ListItemCollectionPosition = new ListItemCollectionPosition
{
PagingInfo = "Paged=TRUE&p_ID=1002&p_FileLeafRef=A1"
};
var items = list.GetItems(camlQuery);
For getting results sorted by object type you could utilize FSObjType
property, for example the following CAML expressions tells server to return folder items first and then file items:
<OrderBy Override='TRUE'>
<FieldRef Name='FSObjType' Ascending='False' />
</OrderBy>
Regarding ListItemCollectionPosition.PagingInfo
property, the following expression tells to return items that come after the item with ID specified via p_ID
parameter and sorted by object type:
var camlQuery = new CamlQuery();
camlQuery.ListItemCollectionPosition = new ListItemCollectionPosition
{
PagingInfo = "Paged=TRUE&p_FSObjType=1&p_ID=200"
};
Example
The following example returns 200
items:
100
Code:
var itemsCount = 200;
var startItemId = 100;
var queryText = @"
<View>
<Query>
<OrderBy Override='TRUE'>
<FieldRef Name='FSObjType' Ascending='False' />
</OrderBy>
</Query>
<RowLimit>
{0}
</RowLimit>
</View>";
var camlQuery = new CamlQuery
{
ViewXml = string.Format(queryText, itemsCount),
ListItemCollectionPosition = new ListItemCollectionPosition
{
PagingInfo = $"Paged=TRUE&p_FSObjType=1&p_ID={startItemId - 1}"
}
};
var items = list.GetItems(camlQuery);
ctx.Load(items);
ctx.ExecuteQuery();
Update
The example of PagingInfo
expression for items to be sorted by type first and then by name:
Paged=TRUE&p_FSObjType=1&p_FileLeafRef=B2&p_ID=100