SharePoint 2010. PostBack для Fluent Ribbon API
Пост о том как добавить серверную обработку нажатия на кнопку на рибоне, созданном с помощью SharePoint 2010 Fluent Ribbon API.
Новое в коде
FluentRibbon.Definitions.Controls.ButtonBaseDefinition
Первое, что нам понадобится - регистрация методов-обработчиков событий.
Для начала добавим два поля: первое для регистрации метода-обработчика, второе для хранения аргумента:
- /// <summary>
- /// PostBack argument
- /// </summary>
- public string ButtonActionArgument = string.Empty;
-
- /// <summary>
- /// PostBackaction
- /// </summary>
- public Action<string> ButtonAction;
PostBack на стороне клиента будет вызываться стандартным javascript-методом __doPostBack. В качестве аргументов этому методу мы будем передавать уникальный идентификатор кнопки (свойство FullId) и сам аргумент из поля ButtonActionArgument. Следуя вышесказанному заменим поле CommandJavaScript в классе на одноименное свойство с несложной логикой:
- /// <summary>
- /// Javascript will be run when button is pressed.
- /// Required for all types of buttons.
- /// By default, button does nothing.
- /// </summary>
- public string CommandJavaScript
- {
- get
- {
- if (ButtonAction == null)
- return _commandJavaScript;
- return string.Format("{0}; __doPostBack('{1}',{2});",
- _commandJavaScript,
- FullId,
- ButtonActionArgument);
- }
- set
- {
- _commandJavaScript = value;
- }
- }
-
- private string _commandJavaScript;
В этом свойстве я оставил вызов стандартной javascript-команды перед отправкой формы на сервер. В таком случае надо быть внимательней и избегать возврата управления (return) в javascript'е.
Обработка PostBack'а на сервере
Теперь осталось реализовать вызов делегата, указанного в новом поле ButtonAction. Я сделал это на примере класса FluentRibbon.RibbonControl:
- protected override void OnLoad(EventArgs e)
- {
- base.OnLoad(e);
- // Если PostBack'а не было, то выходим
- if (!Page.IsPostBack) return;
- var target = Request.Form["__EVENTTARGET"];
- var argument = Request.Form["__EVENTARGUMENT"];
- // Получаем таб
- var tabs = GetTabDefinition();
- var controls = new List<ButtonBaseDefinition>();
- // Перебираем группы на рибоне
- if (tabs.Groups.Length > 0)
- {
- // Кнопки верхнего уровня, расположенные на рибоне
- var firstLevelControls = tabs.Groups
- .SelectMany(g => g.Controls)
- .OfType<ButtonBaseDefinition>();
- // Кнопки второго уровня, расположенные
- // внутри контейнеров
- var secondLevelControls = firstLevelControls
- .OfType<IContainer>()
- .SelectMany(c => c.Controls)
- .OfType<ButtonBaseDefinition>();
-
- controls.AddRange(firstLevelControls);
- controls.AddRange(secondLevelControls);
-
- // Ищем наш контрол
- var targetControl = controls
- .Where(c => c.FullId == target)
- .FirstOrDefault();
- // Если контрол найден и действие указано, то вызываем его, передав аргумент
- if (targetControl != null)
- {
- if (targetControl.ButtonAction != null)
- {
- targetControl.ButtonAction.Invoke(argument);
- }
- }
- }
- }
Вот и все изменения нам необходимые. Я привел пример только для класса FluentRibbon.RibbonControl. Для реализации этой функциональности в классе FluentRibbon.RibbonLayoutsPage, придется либо копировать её из RibbonControl'а, либо выносить в третий класс.
Результат
Теперь классы в проекте выглядят несколько иначе:
Применение
Очень просто и понятно, я думаю, без дополнительных комментариев:
- public override TabDefinition GetTabDefinition()
- {
- // Создаем кнопку, вызывающую PostBack
- var postBackButton = new ButtonDefinition
- {
- Id = "PostBackButton",
- Title = "PostBack Button",
- Image = ImageLibrary.GetStandardImage(10, 10),
- ButtonAction = CustomRibbonButtonDefinition
- };
- // Возвращаем таб с PostBack-кнопкой
- return new TabDefinition()
- {
- Id = "PostBackTab",
- Title = "PostBackTab",
- Groups = new[]
- {
- new GroupDefinition()
- {
- Id = "PostBackGroup",
- Title = "PostBackGroup",
- Template = GroupTemplateLibrary.SimpleTemplate,
- Controls = new ControlDefinition[] {postBackButton}
- }
- }
- };
- }
-
- // Обработчик нажатия на PostBack-кнопку
- public void CustomRibbonButtonDefinition(string arg)
- {
- var id = 0;
- if(int.TryParse(arg, out id))
- {
- //var repository = new DocumentRepository();
- // ...
- }
- }
JavaScript в качестве аргумента
Также можно в качестве аргумента передавать какую-нибудь javascript-функцию. Примерно вот так:
- // Создаем кнопку, вызывающую PostBack
- var postBackButton = new ButtonDefinition
- {
- Id = "PostBackButton",
- Title = "PostBack Button",
- Image = ImageLibrary.GetStandardImage(10, 10),
- ButtonAction = CustomRibbonButtonDefinition,
- ButtonActionArgument = "SP.ClientContext.get_current().get_url()"
- };
Update
Также рекомендую почитать пост Андрея Маркеева и комментарии к нему здесь.