Пользователи SharePoint знают, что создавая или редактируя какой-либо элемент, указывать время можно с интервалом в 5 минут. В большинстве случаев этого достаточно. Однако, встречаются такие заказчики, которых это не устраивает. Они хотят встречи назначать в 12:02, требовать выполнения задачи к 16:31, обращения пользователей регистрировать с точностью до минуты. Их право, они за это деньги платят.
Попросить SharePoint считать не по пять минут, а по одной, стандартными средствами не представляется возможным. Некоторые знакомые к такой задаче устраивали пляски с SharePoint Designer'ом и Visual Studio, пытаясь соорудить кастомные формы и/или FieldType'ы. На мой взгляд, есть более красивое решение. Кому интересно, добро пожаловать под кат.
Теория
SharePoint активно использует систему шаблонов. Для списочного типа контента по умолчанию установлен шаблон UserList. Его легко можно изменить на любой другой через определение типа контента или с помощью небезызвестного SharePoint Manager прямо на работающем сервере. Определения шаблонов лежат в %SharePointRoot%CONTROLTEMPLATECONTROLTEMPLATESDefaultTemplates.ascx.
Не многие начинающие знают, что для отображения полей элементов так же используются шаблоны. Однако, в определении Field'а невозможно задать какой шаблон ему нужно использовать. Воспользуемся особенностью использования SharePoint'ом шаблонов: SharePoint сначала загружает стандартные шаблоны, потом все остальные. Если идентификаторы шаблонов совпадают, то для отображения используется последний загруженный. В связи с этим нам остается лишь переопределить стандартный шаблон.
Практика
Стандартный шаблон DateTime-поля для отображения использует DateTimeControl. Значит нам нужно заменить именно этот контрол. Заменять будем наследником.
public class CustomDateTimeControl : DateTimeControl
Путем декомпиляции логических рассуждений определяем идентификатор выпадающего списка, который отображает пользователю минуты, и находим его в дочерних контролах:
private DropDownList _minuteDropDownList;
protected override void CreateChildControls()
{
base.CreateChildControls();
var minutesId = base.ID + "DateMinutes";
_minuteDropDownList = FindControl(minutesId) as DropDownList;
}
Привязка данных в этом списке происходит на этапе PreRender, поэтому после того, как родительский класс сделает привязку, мы эту привязку переопределим:
protected override void OnPreRender(EventArgs e)
{
base.OnPreRender(e);
if (_minuteDropDownList != null && !DateOnly)
{
_minuteDropDownList.DataSource = _minutes;// массив отображаемых минут.
_minuteDropDownList.DataBind();
_minuteDropDownList.SelectedIndex = SelectedDate.Minute;
}
}
Теперь создаем ascx-файл, в котором будет храниться новый шаблон.
<SharePoint:RenderingTemplate ID="DateTimeField" runat="server">
<Template>
<CustomTag:CustomDateTimeControl runat="server" ID="DateTimeField"/>
</Template>
</SharePoint:RenderingTemplate>
После разворачивания решения поле даты будет содержать выпадающий список минут с интервалом в 1 минуту.
Заключение
Следует помнить, что данное решение будет влиять на все сайты приложения, на котором развернуто решение.
Автор: ejikfast