SPFieldIterator наше все или как изменить внешний вид List Form в SharePoint
Если вы уже сталкивались с задачами кастомизацией видимости полей в элементе или задачами связанными с расширением формы элемента, то вы наверное уже заходили на блоги именитых в Рунете блоггеров, которые публиковали подобного рода статьи. И во многих идет перевес в сторону использования SPD (в простонародье SharePointDesigner ).
Хочу немного поделиться своими впечатлениями по работе с данной кастомизацией и покажу небольшой пример.
Шаблон по которому рисуются формы списков находится в файле DefaultTemplates.ascx (папка CONTROLTEMPLATES) и называется ListForm (Листинг 1).
Листинг 1. Шаблон по которому рисуются формы списков — ListForm
Контрол
<SharePoint:ListFieldIterator runat=«server»/>
отвечает за вывод полей. Идея заключается в том, что бы сделать свой ListFieldIterator и подключить его для нужных списков.
Можно сделать несколько ListFieldIterator-оров для разных списков, можно даже для каждой формы (NewForm.aspx, DispForm.aspx, EditForm.aspx) одного и того же списка назначить свой итератор.
1. Сделать наследника ListFieldIterator — Листинг 2.
Листинг 2. Наследник ListFieldIterator который прячет и переводит в ReadOnly заданные поля
Ничего сложного. Здесь для каждого поля, которое нужно отобразить, создается свой ListFieldIterator с нужным ControlMode. В ExcludeFields передается строка содержащая поля которые нужно исключить, т.е. все кроме текущего.
2. Сделать файл MyListForm.aspx и положить его в папку CONTROLTEMPLATES
В MyListForm.aspx скопируйте весь <SharePoint:RenderingTemplate id=«ListForm» runat=«server»>, замените id=«ListForm» на id=«MyListForm”, <SharePoint:ListFieldIterator runat=»server"/> на <My:MyFieldIterator runat=«server»> — Листинг 3.
Листинг 3. Свой шаблон вывода формы списков
Отметим, что MyListForm.aspx обязательно должен лежать в корне CONTROLTEMPLATES, если положить в под-папку не взлетит.
3. Указать для какой формы использовать шаблон MyListForm.
Для этого в ListDefinition укажите Template для нужной формы — Листинг 4.
Листинг 4. ListDefinition с указанием шаблонов для вывода форм
Использование итераторов по моему мнению, это штука более динамичная и когда делать кастомизацию надо исходить из того чтобы параметры для работы итератора были описаны где нибудь в независимом месте, я всегда использую для этих дел XML и описываю соответствующую схему или генерирую ее динамически. Должен получаться своего рода контроллер. А если нужно что-то единичное сделать, то можно использовать кучу разных простых и быстрых вариантов (SPD, JS.)
Небольшой пример из жизни.
Задача заключалась в том, что есть папка определенного типа контента и все элементы создаваемые внутри папки наследуют некоторые атрибуты и их необходимо скрыть при создании элемента внутри папки, но надо не забывать что элементы из этого типа контента могут создаются и не в папках с наследованием элементов и в этом случае отображать столбцы для заполнения
Мы используем уже существующий пример и добавляем в него - Листинг 5.
Листинг 5. Проверка родителя
И добавляем дополнительное условие - Листинг 5
Листинг 5. Добавление в условие из Листнига 2 доп условия
В итоге мы скроем поля которые создались внутри папки и покажем их при создание вне папок.
Для того чтобы не повторяться и не было критики на плагиаты вот источник (Который ссылается тоже на источник).
Хочу немного поделиться своими впечатлениями по работе с данной кастомизацией и покажу небольшой пример.
Для начала немного из теории
Шаблон по которому рисуются формы списков находится в файле DefaultTemplates.ascx (папка CONTROLTEMPLATES) и называется ListForm (Листинг 1).
<SharePoint:RenderingTemplate id="ListForm" runat="server">
<Template>
<span id='part1'>
<SharePoint:InformationBar runat="server"/>
<div id="listFormToolBarTop">
<wssuc:ToolBar CssClass="ms-formtoolbar" id="toolBarTbltop" RightButtonSeparator=" " runat="server">
<Template_RightButtons>
<SharePoint:NextPageButton runat="server"/>
<SharePoint:SaveButton runat="server"/>
<SharePoint:GoBackButton runat="server"/>
</Template_RightButtons>
</wssuc:ToolBar>
</div>
<SharePoint:FormToolBar runat="server"/>
<SharePoint:ItemValidationFailedMessage runat="server"/>
<table class="ms-formtable" style="margin-top: 8px;" border="0" cellpadding="0" cellspacing="0" width="100%">
<SharePoint:ChangeContentType runat="server"/>
<SharePoint:FolderFormFields runat="server"/>
<SharePoint:ListFieldIterator runat="server"/>
<SharePoint:ApprovalStatus runat="server"/>
<SharePoint:FormComponent TemplateName="AttachmentRows" runat="server"/>
</table>
<table cellpadding="0" cellspacing="0" width="100%"><tr><td class="ms-formline"><img src="/_layouts/images/blank.gif" width='1' height='1' alt="" /></td></tr></table>
<table cellpadding="0" cellspacing="0" width="100%" style="padding-top: 7px"><tr><td width="100%">
<SharePoint:ItemHiddenVersion runat="server"/>
<SharePoint:ParentInformationField runat="server"/>
<SharePoint:InitContentType runat="server"/>
<wssuc:ToolBar CssClass="ms-formtoolbar" id="toolBarTbl" RightButtonSeparator=" " runat="server">
<Template_Buttons>
<SharePoint:CreatedModifiedInfo runat="server"/>
</Template_Buttons>
<Template_RightButtons>
<SharePoint:SaveButton runat="server"/>
<SharePoint:GoBackButton runat="server"/>
</Template_RightButtons>
</wssuc:ToolBar>
</td></tr></table>
</span>
<SharePoint:AttachmentUpload runat="server"/>
</Template>
</SharePoint:RenderingTemplate>
Листинг 1. Шаблон по которому рисуются формы списков — ListForm
Контрол
<SharePoint:ListFieldIterator runat=«server»/>
отвечает за вывод полей. Идея заключается в том, что бы сделать свой ListFieldIterator и подключить его для нужных списков.
Можно сделать несколько ListFieldIterator-оров для разных списков, можно даже для каждой формы (NewForm.aspx, DispForm.aspx, EditForm.aspx) одного и того же списка назначить свой итератор.
Делаем свой итератор
1. Сделать наследника ListFieldIterator — Листинг 2.
public class MyFieldIterator : ListFieldIterator
{
protected override void CreateChildControls()
{
// массивы названий полей можно получать динамически
// здесь, для примера, они прохардкожены
var readOnlyFieldsInternalNames = new string[] { "Title", "Status" };
var excludeFieldsInternalNames = new string[] { "SalesPoint" };
for (int ii = 0; ii < base.Fields.Count; ii++)
{
var currentFiledInternalName = base.Fields[ii].InternalName;
if (base.IsFieldExcluded(base.Fields[ii]) ||
excludeFieldsInternalNames.Contains(currentFiledInternalName))
continue;
var fieldIterator = new ListFieldIterator()
{
ControlMode = readOnlyFieldsInternalNames.Contains(currentFiledInternalName) ?
SPControlMode.Display :
SPContext.Current.FormContext.FormMode,
ExcludeFields = string.Join(";#", base.Fields.Cast<SPField>()
.Where(ff => ff.InternalName != currentFiledInternalName)
.Select(ff => ff.InternalName).ToArray())
};
this.Controls.Add(fieldIterator);
}
}
}
Листинг 2. Наследник ListFieldIterator который прячет и переводит в ReadOnly заданные поля
Ничего сложного. Здесь для каждого поля, которое нужно отобразить, создается свой ListFieldIterator с нужным ControlMode. В ExcludeFields передается строка содержащая поля которые нужно исключить, т.е. все кроме текущего.
2. Сделать файл MyListForm.aspx и положить его в папку CONTROLTEMPLATES
В MyListForm.aspx скопируйте весь <SharePoint:RenderingTemplate id=«ListForm» runat=«server»>, замените id=«ListForm» на id=«MyListForm”, <SharePoint:ListFieldIterator runat=»server"/> на <My:MyFieldIterator runat=«server»> — Листинг 3.
...
<%@ Register TagPrefix="My" Assembly="$SharePoint.Project.AssemblyFullName$" namespace="My" %>
<SharePoint:RenderingTemplate id="MyListForm" runat="server">
…
<%--<SharePoint:ListFieldIterator runat="server"/>--%>
<My:MyFieldIterator runat="server" />
...
</SharePoint:RenderingTemplate>
Листинг 3. Свой шаблон вывода формы списков
Отметим, что MyListForm.aspx обязательно должен лежать в корне CONTROLTEMPLATES, если положить в под-папку не взлетит.
3. Указать для какой формы использовать шаблон MyListForm.
Для этого в ListDefinition укажите Template для нужной формы — Листинг 4.
...
<Forms>
<Form Type="DisplayForm" Url="DispForm.aspx" SetupPath="pages\form.aspx" WebPartZoneID="Main" />
<Form Type="EditForm" Url="EditForm.aspx" SetupPath="pages\form.aspx" WebPartZoneID="Main" Template="MyListForm" />
<Form Type="NewForm" Url="NewForm.aspx" SetupPath="pages\form.aspx" WebPartZoneID="Main" Template="MyListForm"/>
...
Листинг 4. ListDefinition с указанием шаблонов для вывода форм
Выводы
Использование итераторов по моему мнению, это штука более динамичная и когда делать кастомизацию надо исходить из того чтобы параметры для работы итератора были описаны где нибудь в независимом месте, я всегда использую для этих дел XML и описываю соответствующую схему или генерирую ее динамически. Должен получаться своего рода контроллер. А если нужно что-то единичное сделать, то можно использовать кучу разных простых и быстрых вариантов (SPD, JS.)
Небольшой пример из жизни.
Задача заключалась в том, что есть папка определенного типа контента и все элементы создаваемые внутри папки наследуют некоторые атрибуты и их необходимо скрыть при создании элемента внутри папки, но надо не забывать что элементы из этого типа контента могут создаются и не в папках с наследованием элементов и в этом случае отображать столбцы для заполнения
Мы используем уже существующий пример и добавляем в него - Листинг 5.
private static bool IsParentItem(SPList list, string rootFolderUrl)
{
var parentItem = false;
var check = list.ParentWeb.GetFolder( rootFolderUrl).Exists;
if (check)
{
bool checkItm = list.ParentWeb.GetFolder( rootFolderUrl).Item != null;
if (checkItm)
{
parentItem = list.ParentWeb.GetFolder( rootFolderUrl).Item. ContentType.Parent.Id == {ContentTypeId};
}
}
return parentItem;
}
Листинг 5. Проверка родителя
И добавляем дополнительное условие - Листинг 5
if (base.IsFieldExcluded(base.Fields[ii]) ||
(excludeFieldsInternalNames.Contains(currentFiledInternalName)&& isParent))
continue;
Листинг 5. Добавление в условие из Листнига 2 доп условия
В итоге мы скроем поля которые создались внутри папки и покажем их при создание вне папок.
Для того чтобы не повторяться и не было критики на плагиаты вот источник (Который ссылается тоже на источник).
Комментарии
Отправить комментарий