SharePoint 2010. PostBack для Fluent Ribbon API

Пост о том как добавить серверную обработку нажатия на кнопку на рибоне, созданном с помощью SharePoint 2010 Fluent Ribbon API.

Новое в коде

FluentRibbon.Definitions.Controls.ButtonBaseDefinition

Первое, что нам понадобится - регистрация методов-обработчиков событий.

Для начала добавим два поля: первое для регистрации метода-обработчика, второе для хранения аргумента:

  1. /// <summary>
  2. /// PostBack argument
  3. /// </summary>
  4. public string ButtonActionArgument = string.Empty;
  5.  
  6. /// <summary>
  7. /// PostBackaction
  8. /// </summary>
  9. public Action<string> ButtonAction;

PostBack на стороне клиента будет вызываться стандартным javascript-методом __doPostBack. В качестве аргументов этому методу мы будем передавать уникальный идентификатор кнопки (свойство FullId) и сам аргумент из поля ButtonActionArgument. Следуя вышесказанному заменим поле CommandJavaScript в классе на одноименное свойство с несложной логикой:

  1. /// <summary>
  2. /// Javascript will be run when button is pressed.
  3. /// Required for all types of buttons.
  4. /// By default, button does nothing.
  5. /// </summary>
  6. public string CommandJavaScript
  7. {
  8.     get
  9.     {
  10.         if (ButtonAction == null)
  11.             return _commandJavaScript;
  12.         return string.Format("{0}; __doPostBack('{1}',{2});"
  13.             _commandJavaScript, 
  14.             FullId, 
  15.             ButtonActionArgument);
  16.     }
  17.     set
  18.     {
  19.         _commandJavaScript = value;
  20.     }
  21. }
  22.  
  23. private string _commandJavaScript;

В этом свойстве я оставил вызов стандартной javascript-команды перед отправкой формы на сервер. В таком случае надо быть внимательней и избегать возврата управления (return) в javascript'е.

Обработка PostBack'а на сервере

Теперь осталось реализовать вызов делегата, указанного в новом поле ButtonAction. Я сделал это на примере класса FluentRibbon.RibbonControl:

  1. protected override void OnLoad(EventArgs e)
  2. {
  3.     base.OnLoad(e);
  4.     // Если PostBack'а не было, то выходим
  5.     if (!Page.IsPostBack) return;
  6.     var target = Request.Form["__EVENTTARGET"];
  7.     var argument = Request.Form["__EVENTARGUMENT"];
  8.     // Получаем таб
  9.     var tabs = GetTabDefinition();
  10.     var controls = new List<ButtonBaseDefinition>();
  11.     // Перебираем группы на рибоне
  12.     if (tabs.Groups.Length > 0)
  13.     {
  14.         // Кнопки верхнего уровня, расположенные на рибоне
  15.         var firstLevelControls = tabs.Groups
  16.             .SelectMany(g => g.Controls)
  17.             .OfType<ButtonBaseDefinition>();
  18.         // Кнопки второго уровня, расположенные
  19.         // внутри контейнеров
  20.         var secondLevelControls = firstLevelControls
  21.             .OfType<IContainer>()
  22.             .SelectMany(c => c.Controls)
  23.             .OfType<ButtonBaseDefinition>();
  24.  
  25.         controls.AddRange(firstLevelControls);
  26.         controls.AddRange(secondLevelControls);
  27.  
  28.         // Ищем наш контрол
  29.         var targetControl = controls
  30.             .Where(c => c.FullId == target)
  31.             .FirstOrDefault();
  32.         // Если контрол найден и действие указано, то вызываем его, передав аргумент
  33.         if (targetControl != null)
  34.         {
  35.             if (targetControl.ButtonAction != null)
  36.             {
  37.                 targetControl.ButtonAction.Invoke(argument);
  38.             }
  39.         }
  40.     }
  41. }

Вот и все изменения нам необходимые. Я привел пример только для класса FluentRibbon.RibbonControl. Для реализации этой функциональности в классе FluentRibbon.RibbonLayoutsPage, придется либо копировать её из RibbonControl'а, либо выносить в третий класс.

Результат

Теперь классы в проекте выглядят несколько иначе:

Применение

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

  1. public override TabDefinition GetTabDefinition()
  2. {
  3.     // Создаем кнопку, вызывающую PostBack
  4.     var postBackButton = new ButtonDefinition
  5.                                 {
  6.                                     Id = "PostBackButton",
  7.                                     Title = "PostBack Button",
  8.                                     Image = ImageLibrary.GetStandardImage(10, 10),
  9.                                     ButtonAction = CustomRibbonButtonDefinition
  10.                                 };
  11.     // Возвращаем таб с PostBack-кнопкой
  12.     return new TabDefinition()
  13.                 {
  14.                     Id = "PostBackTab",
  15.                     Title = "PostBackTab",
  16.                     Groups = new[]
  17.                     {
  18.                     new GroupDefinition()
  19.                         {
  20.                             Id = "PostBackGroup",
  21.                             Title = "PostBackGroup",
  22.                             Template = GroupTemplateLibrary.SimpleTemplate,
  23.                             Controls = new ControlDefinition[] {postBackButton}
  24.                         }
  25.                     }
  26.                 };
  27. }
  28.  
  29. // Обработчик нажатия на PostBack-кнопку
  30. public void CustomRibbonButtonDefinition(string arg)
  31. {
  32.     var id = 0;
  33.     if(int.TryParse(arg, out id))
  34.     {
  35.         //var repository = new DocumentRepository();
  36.         // ...
  37.     }
  38. }

JavaScript в качестве аргумента

Также можно в качестве аргумента передавать какую-нибудь javascript-функцию. Примерно вот так:

  1. // Создаем кнопку, вызывающую PostBack
  2. var postBackButton = new ButtonDefinition
  3.                   {
  4.                       Id = "PostBackButton",
  5.                       Title = "PostBack Button",
  6.                       Image = ImageLibrary.GetStandardImage(10, 10),
  7.                       ButtonAction = CustomRibbonButtonDefinition,
  8.                       ButtonActionArgument = "SP.ClientContext.get_current().get_url()"
  9.                   };

Update

Также рекомендую почитать пост Андрея Маркеева и комментарии к нему здесь.

Виталий Жуков

Виталий Жуков

SharePoint архитектор, разработчик, тренер, Microsoft MVP (Office Development). Более 15 лет опыта работы с SharePoint, Dynamics CRM, Office 365, и другими продуктами и сервисами Microsoft.

Смотрите также

Развертывание списков и библиотек с помощью SPFx-решений

Развертывание списков и библиотек с помощью SPFx-решений

SharePoint. Drag-and-Drop Загрузчик файлов

SharePoint. Drag-and-Drop Загрузчик файлов

CSOM. Загрузка файлов

CSOM. Загрузка файлов

SharePoint List REST API. Часть 2

SharePoint List REST API. Часть 2

SharePoint Framework. Создание веб-части на Angular

SharePoint Framework. Создание веб-части на Angular

SharePoint List REST API. Часть 1

SharePoint List REST API. Часть 1

Презентация с доклада о SharePoint Framework

Презентация с доклада о SharePoint Framework

SharePoint Framework. Создаем AngularJS 1.x Client WebPart

SharePoint Framework. Создаем AngularJS 1.x Client WebPart

SharePoint. Регистрация CSS и JavaScript с помощью DelegateControl

SharePoint. Регистрация CSS и JavaScript с помощью DelegateControl

SharePoint. Расширяем REST API

SharePoint. Расширяем REST API

SharePoint Excel Services. Создаем кредитный калькулятор

SharePoint Excel Services. Создаем кредитный калькулятор

SharePoint Ribbon API. Использование ToggleButton

SharePoint Ribbon API. Использование ToggleButton

SharePoint 2013. How To: настройка входящей почты для разработчиков

SharePoint 2013. How To: настройка входящей почты для разработчиков

Мифы и правда о Linq to SharePoint

Мифы и правда о Linq to SharePoint

5 особенностей SPSiteDataQuery

5 особенностей SPSiteDataQuery

SharePoint 2013. Введение в SharePoint App. Часть 2

SharePoint 2013. Введение в SharePoint App. Часть 2

SharePoint 2013. Введение в SharePoint App. Часть 1

SharePoint 2013. Введение в SharePoint App. Часть 1

Превью для веб-части в SharePoint 2010/2013

Превью для веб-части в SharePoint 2010/2013

SharePoint 2013. Еще немного о новых контролах

SharePoint 2013. Еще немного о новых контролах

SharePoint 2013. Контрол ClientPeoplePicker

SharePoint 2013. Контрол ClientPeoplePicker

SharePoint 2013. Контрол ImageCrop

SharePoint 2013. Контрол ImageCrop

SharePoint 2013. Тип поля Geolocation

SharePoint 2013. Тип поля Geolocation

Создание типа поля в SharePoint

Создание типа поля в SharePoint

SharePoint 2010. Длительные операции с обновляемым статусом

SharePoint 2010. Длительные операции с обновляемым статусом

Linq to SharePoint. Создаем ContentIterator

Linq to SharePoint. Создаем ContentIterator

Linq to SharePoint. Получение данных из другой коллекции сайтов

Linq to SharePoint. Получение данных из другой коллекции сайтов

Linq to SharePoint. Версионность

Linq to SharePoint. Версионность

SharePoint. Получение URL-адреса иконки для документа

SharePoint. Получение URL-адреса иконки для документа

Linq to SharePoint. Блокировка документов

Linq to SharePoint. Блокировка документов

Linq to SharePoint. Паттерн Repository

Linq to SharePoint. Паттерн Repository

Linq to SharePoint. Получение мета-данных списка

Linq to SharePoint. Получение мета-данных списка

Linq to SharePoint. Мапинг полей

Linq to SharePoint. Мапинг полей

Linq to SharePoint. Формирование данных для ProcessBatchData

Linq to SharePoint. Формирование данных для ProcessBatchData

Linq to SharePoint. Сравнение производительности с Camlex.NET

Linq to SharePoint. Сравнение производительности с Camlex.NET

Linq to SharePoint. Часть 5. Поля Choice и MultiChoice

Linq to SharePoint. Часть 5. Поля Choice и MultiChoice

Linq to SharePoint. Часть 4. Dynamic LINQ

Linq to SharePoint. Часть 4. Dynamic LINQ

Linq to SharePoint. Особенности. Часть 3

Linq to SharePoint. Особенности. Часть 3

Linq to SharePoint. Особенности. Часть 2

Linq to SharePoint. Особенности. Часть 2

SharePoint 2010. PeopleEditor. Установка значения

SharePoint 2010. PeopleEditor. Установка значения

SharePoint 2010. Настройка входящей почты для кастомного списка

SharePoint 2010. Настройка входящей почты для кастомного списка

Linq to Sharepoint. Особенности

Linq to Sharepoint. Особенности

EntityFramework. Оптимистические блокировки

EntityFramework. Оптимистические блокировки