Введение
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 аттрибуте.