В своей самой первой статье блога я рассказывал об отображении значений столбцов в шаблоне отображения полей (RenderPattern) DisplayPattern с применением веб-служб и JavaScript. Этот способ довольно неплох, за исключением одного НО - при больших объемах отображаемых данных, производительность падает! Это связано с тем, что каждый раз совершается вызов веб-службы, если значение столбца не пусто, и собственно парсится wsdl ответ. Возможно, этот способ вывода значений и удовлетворил конечного пользователя при данном типе столбца (вряд ли столбец метаданных потребуется широкой аудитории), но с типом «Расширенная подстановка» данный финт бы не прошел.
Конечно, первое наперво, что приходит в голову для автоматизации – вызов единожды веб-службы с передачей массива неповторяющиеся значений столбца. Ну, а вместо XML лучше выбрать другой формат данных, без лишних сложностей. Одним из лучших способов выбрать необходимые элементы на странице HTML является использование jQuery. А передавать и получать данные лучше всего при выборе данного фреймворка в формате JSON, тем более что для работы с ним в .NET Framework 3.5 SP1 имеются необходимые метаданные.
Поскольку вызов веб-службы будет происходить единожды, то лучше сделать это нужно по событию элемента, находящегося в шаблоне отображения полей HeaderPattern. Таким будет являться опять же элемент iframe с событием onload. Ниже приведена часть кода HeaderPattern, относящегося к данной задаче.
<RenderPattern Name="HeaderPattern"> <HTML><![CDATA[<script src="/_layouts/jQuery/jquery-1.6.4.js"></script>]]></HTML> <HTML><![CDATA[<script src="/_layouts/jQuery/json2.js"></script>]]></HTML> <HTML><![CDATA[<script src="/_layouts/ExtLookup.js"></script>]]></HTML> <HTML><![CDATA[<iframe id="Header]]></HTML> <List/> <Property Select="Name"/> <HTML><![CDATA[" height="0" width="0" onl oad="GetExtValueAJAX("div_]]></HTML> <List/> <Property Select="Name"/> <HTML><![CDATA[", "]]></HTML> <HttpVDir/> <HTML> <![CDATA[", "]]> </HTML> <List/> <HTML> <![CDATA[", "]]> </HTML> <Property Select="Name"/> <HTML> <![CDATA[");"></iframe>]]> </HTML> </RenderPattern>
Файл, json2.js, JavaScript реализацию JSON-парсера можно взять, предварительно с ним познакомившись из JSON in JavaScript. Сам ExtLookup.js – скрипт, содержащий в себе реализацию метода GetExtValueAJAX. Код его приведен ниже.
function GetExtValueAJAX(divname, siteurl, listid, fieldname) { $(document).ready(function () { // инициализация массивов для отбора неповторяющимся значений var mass = []; var vass = []; // замена мета-символов в селекторе divname = divname.replace("{", "\\{").replace("}", "\\}"); // выборка элементов div, относящихся к столбцу var divs = $('div[id^=' + divname + ']').toArray(); $.each(divs, function() { if (this.extvalue != "") { // заполенение массива mass неповторяющимися значения столбца (значениями атрибута extvalue) if ($.inArray(this.extvalue, vass) == -1) { vass.push(this.extvalue); mass.push({ "Value": this.extvalue, "Display": "" }); } } }); // вызов веб-службы для получения $.ajax({ type: "POST", url: siteurl + "/_vti_bin/WSJSONExtLookup.asmx/GetExtLookupValue", // передача данных в виде строки объектов в формате JSON dat a: "{ value:'" + JSON.stringify(mass) + "', listID: '" + listid + "', fieldName: '" + fieldname + "'}", contentType: "application/json; charset=utf-8", success: function ExtValueSuccess(response) { // получение результата var extVals = eval('(' + response.d + ')'); $.each(divs, function() { if (this.extvalue != "") { // замена содержимого эелемента div соответствующим значению столбца HTML-кодом $(this).html(RenderExtLookupJSON(this.extvalue, extVals)); } }); }, dataType: "json", failure: ExtValueCallFailed }); }); return 0; } function ExtValueCallFailed() { // вывод ошибки } function RenderExtLookupJSON(val, extVals) { var res = ""; $.each(extVals, function () { if (this.Value == val) { res += this.Display + "<br/>"; } }); return res; }
В начале отбираются неповторяющиеся значения атрибутов extvalue элементов div, относящихся к данному столбцу, а потом передаются в качестве параметра веб-службе, которая их обрабатывает и выдает значения для отображения также в формате JSON. И затем по соответствующим значениям атрибута extvalue заменяется содержимое элементов div.
Полную ясность понимания работы скрипта даст невозможно без описания шаблона отображения полей DisplayPattern. Именно в нём задаются значения ID элементов div отображения значения столбца, здесь же прописывается атрибут extvalue с соответствующим значением самого столбца.
Полную ясность понимания работы скрипта даст невозможно без описания шаблона отображения полей DisplayPattern. Именно в нём задаются значения ID элементов div отображения значения столбца, здесь же прописывается атрибут extvalue с соответствующим значением самого столбца.
<RenderPattern Name="DisplayPattern"> <HTML> <![CDATA[<div id="div_]]> </HTML> <List/> <Property Select="Name"/> <Field Name="ID"/> <HTML> <![CDATA[" extvalue="]]> </HTML> <Column/> <HTML> <![CDATA["></div>]]> </HTML> </RenderPattern>
Серверная часть - код веб-службы приведен ниже. Здесь приведены только фрагменты кода по главным ключевым моментам, а именно классу DataContractJsonSerializer для работы с форматом JSON и описание класса, инкапсулирующего данные JSON. Сама реализация вывода значений в формате HTML зависит от фантазии разработчика.
[System.Runtime.Serialization.DataContract] public class ExtLookupValueJSON { public ExtLookupValueJSON() { } public ExtLookupValueJSON(string value, string display) { this.Value = value; this.Display = display; } [System.Runtime.Serialization.DataMember(Name = "Value")] public string Value { get; set; } [System.Runtime.Serialization.DataMember(Name = "Display")] public string Display { get; set; } } [WebService(Namespace = "http://tempuri.org/")] [WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)] [System.Web.Script.Services.ScriptService] public class WSJSONExtLookup : WebService { public WSJSONExtLookup() { } [WebMethod] [ScriptMethod(ResponseFormat = ResponseFormat.Json)] public string GetExtLookupValue(string value, string listID, string fieldName) { List<ExtLookupValueJSON> list=new List<ExtLookupValueJSON>(); DataContractJsonSerializer serializer = new DataContractJsonSerializer(list.GetType()); using (MemoryStream ms = new MemoryStream(Encoding.Default.GetBytes(value))) { list = (List<ExtLookupValueJSON>)serializer.ReadObject(ms); ms.Close(); } [...] string jsonString = ""; using (MemoryStream ms = new MemoryStream()) { serializer.WriteObject(ms, res); jsonString = Encoding.UTF8.GetString(ms.ToArray()); ms.Close(); } return jsonString; } }
Единственным недостатком данного решения является открытая визуальность вывода значений. Как известно, jQuery срабатывает, когда страница полностью загружена. Так вот после её загрузки конечный пользователь может наблюдать последовательный вывод элементов, относящихся к столбцам данного типа. По времени занимает это считанные секунды и гораздо приятней наблюдать последовательную загрузку страницы, нежели ждать её полного появления при эффекте зависания.
English version - SharePoint Extended lookup field. Part 2: Value display in ListViewWebPart using jQuery+JSON
English version - SharePoint Extended lookup field. Part 2: Value display in ListViewWebPart using jQuery+JSON
Комментариев нет:
Отправить комментарий