29 авг. 2012 г.

Обработка изменения размеров окна

Когда мы меняем размер окна браузера, размеры ленты и рабочей области на сайте SharePoint пересчитываются заново и устанавливаются с помощью скриптов. Корректировка размеров ленты и рабочей области происходит в глобальной функции FixRibbonAndWorkspaceDimensions, которая определена в файле init.js.
Существует возможность добавить свои обработчики изменения размеров окна. Для этого достаточно добавить функцию-обработчик в глобальный массив g_workspaceResizedHandlers.
Например, выполнив в консоли браузера такой код (опустив лишние проверки), вы сможете видеть ширину и высоту рабочей области после изменения размеров окна:
function logWorkspaceSize() {
    var ws = document.getElementById('s4-workspace');
    console.log(ws.style.width + ' x ' + ws.style.height);
};
 
g_workspaceResizedHandlers.push(logWorkspaceSize);

Можно добавлять обработчик не напрямую, а через клиентскую модель: 

SP.UI.Workspace.add_resized(logWorkspaceSize);

Есть в SharePoint один неприятный момент, связанный с изменением размеров элементов страницы: на странице со списком, если в представлении много колонок и они не убираются на экран, появляется прокрутка, при этом вкладка ленты "Обзор" и уведомления (которые SP.UI.Status) подгоняются под размер окна, а не представления.



Используя свой обработчик, можно это исправить:

  ExecuteOrDelayUntilScriptLoaded(function () {
    SP.UI.Workspace.add_resized(function () {
      var title = document.getElementById('s4-titlerow'),
      status = document.getElementById('s4-statusbarcontainer'),
      contentDivTable = document
        .getElementById('ctl00_MSO_ContentDiv')
        .getElementsByTagName('table')[0],
      contentTable = document.getElementById('MSO_ContentTable'),
      delta = contentDivTable.offsetWidth - contentTable.offsetWidth,
      newWidth = 0;
 
      if (delta > 0) {
        newWidth = title.offsetWidth + delta + 'px';
        title.style.width = newWidth;
        status.style.width = newWidth;
      }
    });
  }, 'init.js');
Функция FixRibbonAndWorkspaceDimensions не вызывается, если страница открыта в модальном окне, т.е. если в строке запроса присутствует параметр IsDlg=1. В этом случае надо самому устанавливать обработчик на изменение размеров окна.

28 авг. 2012 г.

Как получить экземпляр рабочего процесса

Перегружая методы класса SPWorkflowEventReceiver, мы можем обрабатывать события, связанные с рабочими процессами, например, запуск и остановку РП. Единственный источник данных о РП, для которого произошло событие, это объект типа SPWorkflowEventProperties.
Кроме InstanceId и WebUrl никаких других данных, идентифицирующих РП, не предоставляется. Нормальные люди для получения экземпляра РП используют конструктор SPWorkflow(SPWeb, Guid).

Не заметив сначала этот конструктор, я решил лезть в БД содержимого для извлечения необходимой информации. Всё же забывать о БД не стоит, потому как она может пригодиться для получения, например, всех РП, запущенных на элементах узла: выбираем записи по ИД узла, группируем по ИД списка и элемента. Можно ещё и по статусу отфильтровать. Будет работать быстрее, чем обход всех списков и элементов.

using (var connection = new SqlConnection(web.Site.ContentDatabase.DatabaseConnectionString))
{
    string commandText = 
        "select ListId, ItemId, Id from Workflow where WebId='" + web.ID + "'";

    using (var command = new SqlCommand(commandText, connection))
    {
        connection.Open();

        using (var reader = command.ExecuteReader())
        {
            if (reader.Read())
            {
                Guid listId = (Guid)reader["ListId"];
                int itemId = (int)reader["ItemId"];
                Guid workflowId = (Guid)reader["Id"];

                // группируем, как надо, и возвращаем результат
            }
        }
    }
}