Введение
ListViewByQuery контрол умеет рендерит view любого листа на основе запроса.

Когда контрол покажет юзеров можно будет их отсортировать или применить к ним фильт, но эти события требуют собственной реализаци.
Синтакс
ListViewByQuery контрол это часть
Microsoft.SharePoint.dll и расположен в пространстве
Microsoft.SharePoint.WebControls. Обявлять нужно так:
<spuc:ListViewByQuery ID="CustomersListViewByQuery" runat="server" Width="700px" />
Так он работать не будет, свойства
List и
Query можно установить только из кода.
Не забывайте добавить вверху страницы:
<%@ Register TagPrefix="spuc" Namespace="Microsoft.SharePoint.WebControls"
Assembly="Microsoft.SharePoint, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %>
Можно создать контрол прямо из кода:
private ListViewByQuery CustomersListViewByQuery;
private void EnsureChildControls()
{
CustomersListViewByQuery = new ListViewByQuery();
// The rest of the code follows here....
}
Для нормальной работы требуется установить несколько обязательных свойств:
List тип которого
SPList и
Query тип которого
SPQuery. В
OnLoad или
EnsureChildControls можно добавить код:
list = SPContext.Current.Web.Lists["Customers"];
CustomersListViewByQuery.List = list;
string query = null;
if (!Page.IsPostBack)
{
query = "<OrderBy><FieldRef Name='Title' Ascending='true' /></OrderBy>";
}
else
{
// apply filtering and/or sorting
}
SPQuery qry = new SPQuery(list.DefaultView);
qry.Query = query;
CustomersListViewByQuery.Query = qry;
Запрос обязательно должен строиться на существующем view листа или контрол не будет работать. Данные в контроле отображаются согласно переданному запросу.
Можно устанавливать ограничение на кол-во возвращаемых записей
RowLimit:
qry.RowLimit = 50;
Сортировка
Юзер может сортировать колонку стандартным кликаньем на header колонки и выбрав
A on Top or
Z on Top.
Это генерирует post back, и данные будут переданы на серверную сторону для обработки сохраненные в
Context.Request["SortField"] и
Context.Request["SortDir"]. Следующий код показывает как можно работать с ними.
if (!Page.IsPostBack)
{
query = "<Query><OrderBy><FieldRef Name='Title' Ascending='true' /></OrderBy></Query>";
}
else
{
// apply filtering and/or sorting
if (this.Context.Request != null && this.Context.Request["SortField"] != null)
{
string sortorder = BuildSortOrder(this.Context.Request["SortField"],
(this.Context.Request["SortDir"] == "Asc" ? "true" : "false"));
if (string.IsNullOrEmpty(query))
query = sortorder;
else
query += sortorder;
}
}
private string BuildSortOrder(string fieldName, string sortOrder)
{
string query = null;
if (!string.IsNullOrEmpty(fieldName))
{
query = string.Format("<OrderBy><FieldRef Name='{0}' Ascending='{1}' /></OrderBy>", fieldName, sortOrder);
}
return query;
}
Фильтрация
Также юзер может фильтровать данные в ListViewByQuery контроле
После этого также происходит posting back, выбранное поле хранится в Context.Request["FilterField1"], а выбранное значение в Context.Request["FilterValue1"]. Если фильтров более чем один (например выбран ещё один фильтр в другой колонке) они будут хранится по такому же принципу с именами FilterField2 и FilterValue2.
private string BuildFilter()
{
string query = "{0}";
bool isFound = true;
int counter = 1;
while (isFound)
{
string filterfield = "FilterField" + counter.ToString();
string filtervalue = "FilterValue" + counter.ToString();
if (this.Context.Request[filterfield] != null && this.Context.Request[filtervalue] != null)
{
// Field type must be treated differently in case of other data type
if (counter > 1)
query = "<And>" + query + "{0}</And>";
query = string.Format(query, string.Format("<Eq><FieldRef Name='{0}' /><Value Type='Text'>{1}</Value></Eq>",
this.Context.Request[filterfield], this.Context.Request[filtervalue]));
counter++;
}
else
{
isFound = false;
}
}
if (!string.IsNullOrEmpty(query))
query = "<Where>" + query + "</Where>";
return query;
}
Этот код будет работать только для текстовых полей. Если необходимы другие типы, например
number, choice или lookup, необходимо использовать так:
SPField field = list.Fields[filterfield];
query = string.Format(query, string.Format("<Eq><FieldRef Name='{0}' /><Value Type='{1}'>{2}</Value></Eq>",
this.Context.Request[filterfield], field.TypeAsString, this.Context.Request[filtervalue]));
Группировка
ListViewByQuery контрол может также гррупировать элементы, для этого нужно использовать CAML GroupBy элемент:
query = "<GroupBy Collapse='FALSE'><FieldRef Name='CountryRegionName' /><FieldRef Name='City' /></GroupBy>";
Этот пример группирует данные по CountryRegionName и по City.
Если вы решили показать сразу сгруппированый вариант, установите Collapse аттрибут в TRUE и
получите:
Но здесь есть проблема, если они сгруппированы по умолчанию, то при открытиии вы получити
только надпись Loading и никаких данных.
Эта проблема решается так: устанавливаем Collapse аттрибут в FALSE и размещаем наш ListViewByQuery контрол
в DIV, затем задаём у дива ID. Ниже дива вставляем скрипт:
<div id="ViewDiv" class="ms-authoringcontrols" style="width:700px">
<spuc:ListViewByQuery ID="CustomersListViewByQuery" runat="server" Width="700px" />
</div>
<script language="javascript">
ExpLinkFormer = function(divId)
{
this._DivId = divId;
this._init();
}
ExpLinkFormer.prototype = {
_init: function() {
var div = document.getElementById(this._DivId);
var links = div.getElementsByTagName("a");
for (var i = 0; i < links.length; i++) {
if (links[i].href == "javascript:" && links[i].onclick.toString().indexOf("ExpCollGroup") > -1) {
//alert(links[i]);
links[i].click();
}
}
}
}
var expLnk = new ExpLinkFormer('ViewDiv');
</script>
ListViewByQuery контрол загружает все данные без группировки, но при рендеринге страницы,
клик метод выполняется для всех hyperlinks которые имеют вызов на ExpCollGroup в их href аттрибуте.