Первая часть статьи здесь.
void GetDistinctValues()
{
SPWeb web = SPControl.GetContextWeb(Context);
try
{
Guid listId = new Guid(Request.QueryString["ListId"]);
Guid viewId = new Guid(Request.QueryString["ViewId"]);
SPList list = web.Lists.GetList(listId, true);
SPView view = list.Views[viewId];
SPQuery query = new SPQuery();
query.ViewXml =
view.PropertiesXml.Substring(0, view.PropertiesXml.Length - 2) +
"><Query>" + view.Query + "</Query>" +
"<ViewFields><FieldRef Name='" + SPHttpUtility.HtmlEncode(Request.QueryString["FieldInternalName"]) +
"'/></ViewFields>" + "<RowLimit>1</RowLimit>" +
"<ViewHeader>" +
"<Fields><Field/></Fields>" +
"</ViewHeader>" +
"<ViewBody/><ViewFooter/><ViewEmpty><Fields><Field/></Fields></ViewEmpty></View>";
/// замена текстов гиперссылок филтьруемых значений
SPField fldThis = null;
try
{
fldThis = list.Fields.GetFieldByInternalName(Request.QueryString["FieldInternalName"]);
}
catch { }
if (fldThis != null)
{
if (fldThis.GetType().ToString() == "[Тип столбца]")
{
string ddlFilter = list.RenderAsHtml(query);
ddlFilter = UpdateMetadataFilter(web.Site.Url, ddlFilter);
Response.Write(ddlFilter);
return;
}
}
///
Response.Write(list.RenderAsHtml(query));
}
catch { }
Response.AddHeader("Cache-Control", "no-cache");
}
С функцией проверки значения строки по шаблону GUID особых проблем нет:
Теперь выпадающий список фильтрации имеет более привлекательный для пользования вид.
English version - SharePoint Metadata field. Part 2: Custom Filter.aspx page.
Второй важный момент, которому стоит уделить внимание при разработке настраиваемого типа столбца SharePoint - это отображение значений столбцов в шаблоне отображения (RenderPattern) под названием HeaderPattern, а точнее, отображение фильтруемых значений в заголовке столбца
В описываемом типе столбца внешне CAML-разметка шаблона, по сути, ничем не будет отличаться от такого же HeaderPattern, как скажем, у типа Lookup, за исключением первой строки, приведенной в первой части статьи. Изменения здесь коснутся страницы /_layouts/Filter.aspx, на которую происходит запрос при клике на заголовке столбца.
В описываемом типе столбца внешне CAML-разметка шаблона, по сути, ничем не будет отличаться от такого же HeaderPattern, как скажем, у типа Lookup, за исключением первой строки, приведенной в первой части статьи. Изменения здесь коснутся страницы /_layouts/Filter.aspx, на которую происходит запрос при клике на заголовке столбца.
Если посмотреть на результат запроса после проведения кастомизации, рассказанной в первой части статьи, то результат малоудовлетворительный:
В текстах гиперссылках – различные значения столбцов, представленные по ранее оговоренному шаблону хранения значений столбцов данного типа: [URL узла][Разделитель][ID списка]. Задача будет состоять в корректном выводе текстов гиперссылок. Лучшим способом решения данной задачи будет простая замена текстов гиперссылок в уже сформированной для фильтрации HTML-разметке в функции GetDistinctValues() в коде страницы /_layouts/Filter.aspx. Т.е., заменить тексты гиперссылок фильтрации, представленных в виде URL узлов и ID списков на соответствующие названия узлов и списков. Также следует учесть, что данное изменение коснется только разрабатываемого типа столбцов. Код функции GetDistinctValues() будет выглядеть следующим образом:
void GetDistinctValues()
{
SPWeb web = SPControl.GetContextWeb(Context);
try
{
Guid listId = new Guid(Request.QueryString["ListId"]);
Guid viewId = new Guid(Request.QueryString["ViewId"]);
SPList list = web.Lists.GetList(listId, true);
SPView view = list.Views[viewId];
SPQuery query = new SPQuery();
query.ViewXml =
view.PropertiesXml.Substring(0, view.PropertiesXml.Length - 2) +
"><Query>" + view.Query + "</Query>" +
"<ViewFields><FieldRef Name='" + SPHttpUtility.HtmlEncode(Request.QueryString["FieldInternalName"]) +
"'/></ViewFields>" + "<RowLimit>1</RowLimit>" +
"<ViewHeader>" +
"<Fields><Field/></Fields>" +
"</ViewHeader>" +
"<ViewBody/><ViewFooter/><ViewEmpty><Fields><Field/></Fields></ViewEmpty></View>";
/// замена текстов гиперссылок филтьруемых значений
SPField fldThis = null;
try
{
fldThis = list.Fields.GetFieldByInternalName(Request.QueryString["FieldInternalName"]);
}
catch { }
if (fldThis != null)
{
if (fldThis.GetType().ToString() == "[Тип столбца]")
{
string ddlFilter = list.RenderAsHtml(query);
ddlFilter = UpdateMetadataFilter(web.Site.Url, ddlFilter);
Response.Write(ddlFilter);
return;
}
}
///
Response.Write(list.RenderAsHtml(query));
}
catch { }
Response.AddHeader("Cache-Control", "no-cache");
}
Код метода UpdateExtLookupFilter, который как раз и заменяет тексты гиперссылок фильтруемых значений с вида [URL узла][Разделитель][ID списка] на соответствующие названия узлов и списков, приведен ниже:
string UpdateMetadataFilter(string siteUrl, string webUrl, string sValue) { string sOptionValue, sHttp, sTitle; // отсортируем заодно фильтруемые значения в порядка возрастания SortedList<string, string> sl = new SortedList<string, string>(); string sOptions = ""; Regex RegEx = new Regex(@"<OPTION Value=\""" + "http.*?</OPTION>", RegexOptions.Compiled); MatchCollection mColl = RegEx.Matches(sValue); for (int i = 0; i < mColl.Count; i++) { sOptionValue = mColl[i].Value; Regex RegExHttpValue = new Regex(@"http.*?\""", RegexOptions.Compiled); sHttp = RegExHttpValue.Matches(sOptionValue)[0].Value; sHttp = sHttp.Substring(0, sHttp.Length - 1).Trim(); sTitle = GetMetadataValue(siteUrl, sHttp); if (String.IsNullOrEmpty(sTitle)) sTitle = "null"; Regex RegExOptionText = new Regex(@">.*<", RegexOptions.Compiled); sOptionValue = sOptionValue.Replace(RegExOptionText.Matches(sOptionValue)[0].Value, ">" + sTitle + "<"); sl.Add(sTitle, sOptionValue); sOptions += sOptionValue; sValue = sValue.Replace(mColl[i].Value, sOptionValue); } string sNeedValue = ""; foreach (KeyValuePair<string, string> key in sl) sNeedValue += key.Value; sValue = sValue.Replace(sOptions, sNeedValue); return sValue; }
Функция GetMetadataValue получения названия веб-узла по его URL и названия списка по его ID, применяемая в методе UpdateExtLookupFilter выглядит так:
string GetMetadataValue(string siteUrl, string value) { string res = ""; char valuesDelimeter = ';'; if (!String.IsNullOrEmpty(value)) { string[] values = value.Split(valuesDelimeter); string webUrl = values[0]; string listID = values[1]; using (SPSite site = new SPSite(siteUrl)) { using (SPWeb web = site.OpenWeb((site.ServerRelativeUrl + webUrl.Substring(site.Url.Length)).Replace("//", "/"))) { SPList list = null; // проверка существования списка по его GUID if (IsGUID(listID)) { try { list = web.Lists.GetList(new Guid(listID), false); } catch { } } if (list != null) res = web.Title + valuesDelimeter + list.Title; } } } return res; }
Здесь обязательно следует учитывать корректный подход к методу Dispose() классов SPSite и SPWeb - Рекомендации: использование высвобождаемых объектов служб Windows SharePoint Services . Хорошим контроллером в этом случае является утилита SPDisposeCheck - SharePoint Dispose Checker Tool.
С функцией проверки значения строки по шаблону GUID особых проблем нет:
bool IsGUID(string expression) { if (expression != null) { Regex guidRegEx = new Regex(@"^(\{){0,1}[0-9a-fA-F]{8}\-[0-9a-fA-F]{4}\-[0-9a-fA-F]{4}\-[0-9a-fA-F]{4}\-[0-9a-fA-F]{12}(\}){0,1}$", RegexOptions.Compiled); return guidRegEx.IsMatch(expression); } return false; }
Теперь выпадающий список фильтрации имеет более привлекательный для пользования вид.
Как отобразить данный тип столбцов на страницах NewForm.aspx и EditForm.aspx – дело вкуса. Множество примеров можно найти на просторах Интернета, поэтому в данной статье этот момент не рассматривается. Стоит только отметить, что в обработках событий тех или иных элементов управления, которые будут входить в шаблоны отображения NewPattern и EditPattern, нужно обязательно учитывать корректный подход к методу Dispose() классов SPSite и SPWeb.
Данную задачу можно расширить до способа хранения других метаданных SharePoint в его же списках и корректного их отображения во всех шаблонах списка. К примеру, на момент написания статьи сюда входили данные, отображенные в области редактирования параметров столбца данного типа ниже:
Данную задачу можно расширить до способа хранения других метаданных SharePoint в его же списках и корректного их отображения во всех шаблонах списка. К примеру, на момент написания статьи сюда входили данные, отображенные в области редактирования параметров столбца данного типа ниже:
English version - SharePoint Metadata field. Part 2: Custom Filter.aspx page.


Комментариев нет:
Отправить комментарий