При запуске бизнес-операции из пользовательского интерфейса контроллер BOExecViewController генерирует ряд событий, обрабатывая которые прикладной разработчик может управлять процессом создания экземпляров интересующих бизнес-операций, инициализацией параметров бизнес-операции, процессом  запуска бизнес-операции на выполнение, а также создания представлений, отображаемых до запуска и после выполнения бизнес-операции. Все события доступны через индексируемое свойство BOExecViewController.BOEvents. Подписку на обработку событий можно выполнять как для конкретной бизнес-операции (передавая ее Id или тип в качестве индекса), так и для всех бизнес-операций (обращаясь непосредственно к полю BOEvents). Далее будут представлены примеры обработчиков.  Рассмотрим эти события.

CreateCustomBusinessOperationInstance

Событие возникает, когда контроллеру BOExecViewController требуется создать экземпляр бизнес-операции. В аргументах передается идентификатор требуемой бизнес-операции.

Обработчик события может создать экземпляр класса бизнес-операции и вернуть его, установив свойство BusinessOperationInstance аргумента.

BusinessOperationExecuting

Возникает перед запуском бизнес-операции. В аргументах события передается информация о вызываемом методе (Execute или Rollback), объект бизнес-операции, и объект класса ShowViewParameters.

Обработчик события может отменить запуск бизнес-операции, установив свойство Cancel в true. В этом случае принимается во внимание состояние объекта  класса ShowViewParameters, с помощью которого можно сообщить пользователю о причине отмены запуска.

BusinessOperationCustomExecute

Событие возникает, когда контроллеру требуется выполнить бизнес-операцию. В аргументах события передается информация о вызываемом методе (Execute или Rollback), объект бизнес-операции, и объект класса ShowViewParameters.

Обработчик события может самостоятельно вызвать требуемый метод бизнес-операции. Чтобы предотвратить запуск бизнес-операции контроллером, обработчик события должен установить свойство Handled аргумента события в true.

При этом в обработчике события требуется самостоятельно организовать ввод параметров бизнес-операции (если они есть), инициализируя поля объекта ShowViewParameters. Также, после завершения бизнес-операции, если нужно отобразить результат, требуется самостоятельно вызвать метод контроллера BOExecViewController.CreateResultViewParameters и самостоятельно обработать полученный объект ShowViewParameters.

CustomizeResultViewParameters

Событие возникает, после выполнения бизнес-операции. В обработчике можно инициализировать поля объекта ShowViewParameters для отображения результатов выполнения бизнес-операции. В аргументах события передается информация о выполненном методе (Execute или Rollback), объект бизнес-операции, и объект класса ShowViewParameters.

ContextPropertyInitializing

Событие возникает при инициализации контекстного свойства.

Подписку на события контроллера BOExecViewController можно проводить в собственном контроллере. Ниже приведен пример подписки на события и их обработки:

 

  /// <summary>

  /// Пример кастомной обработки событий контроллера Xafari.BC.BusinessOperations.Controllers.BOExecViewController

  /// </summary>

  public class CustomizeBusinessOperationsController : ViewController

   {

      private BOExecViewController _boExecViewController;

 

      protected override void OnActivated()

       {

          base.OnActivated();

           _boExecViewController = Frame.GetController<BOExecViewController>();

          if (_boExecViewController != null)

           {

              // Подписка на обработку событий контроллера для конкретных бизнес-операций.

               _boExecViewController.BOEvents[typeof(CalcOrderTotalList)].BusinessOperationExecuting +=

                 CalcOrderTotalListExecuting;

               _boExecViewController.BOEvents[typeof(ReversibleOperation)].BusinessOperationCustomExecute +=

                 ReversibleOperationCustomExecute;

               _boExecViewController.BOEvents[typeof(ChangeFreightContext)].BusinessOperationCustomExecute +=

                 ChangeFreightContextCustomExecute;

               _boExecViewController.BOEvents[typeof(ChangeFreightContext)].CreateCustomBusinessOperationInstance +=

                 CreateCustomChangeFreightContextInstance;

 

              // Подписка на обработку событий контроллера для всех бизнес-операций.

               _boExecViewController.BOEvents.CustomizeResultViewParameters += CustomizeResultViewParameters;

           }

       }

 

      protected override void OnDeactivated()

       {

          if (_boExecViewController != null)

           {

               _boExecViewController.BOEvents[typeof(CalcOrderTotalList)].BusinessOperationExecuting -=

                 CalcOrderTotalListExecuting;

               _boExecViewController.BOEvents[typeof(ReversibleOperation)].BusinessOperationCustomExecute -=

                 ReversibleOperationCustomExecute;

               _boExecViewController.BOEvents[typeof(ChangeFreightContext)].BusinessOperationCustomExecute -=

                 ChangeFreightContextCustomExecute;

               _boExecViewController.BOEvents[typeof(ChangeFreightContext)].CreateCustomBusinessOperationInstance +=

                 CreateCustomChangeFreightContextInstance;

               _boExecViewController.BOEvents.CustomizeResultViewParameters -= CustomizeResultViewParameters;

           }

 

          base.OnDeactivated();

       }

 

      private const int BoundaryYear = 1996;

 

      // Перед запуском БО (в нашем случае это CalcOrderTotalList) можно выполнить корректировку ее параметров.

      // В данном примере из выбранного списка заказов удаляются заказы, не удовлетворяющие определенному условию.

      // Ситуация вымышленная, просто чтобы показать возможность реализации чего-то подобного.

      // Пусть в случае наличия в списке заказа, у которого год RequiredDate меньше 1995-го, бизнес-операция

      // "Стоимость заказов (списковая)" не выполняется, а выдается соответствующее сообщение.

      private void CalcOrderTotalListExecuting(object sender, BusinessOperationExecutingEventArgs e)

       {

          var businessOperation = (CalcOrderTotalList)e.BusinessOperation;

           businessOperation.Orders.RemoveAll(order => order.RequiredDate.Year < BoundaryYear);

          if (businessOperation.Orders.Count == 0)

           {

               MessageObject.CreateMessageWarning(

                   e.ShowViewParameters,

                   Application,

                  "Внимание",

                  "Стоимость заказов, требуемых до {0}г. вычислять почему-то запрещено." + Environment.NewLine +

                  "После удаления таких заказов из списка выбранных там ничего не осталось." + Environment.NewLine +

                  "Выберите другие заказы.",

                   BoundaryYear

               );

 

               e.Cancel = true;

           }

       }

 

      // Отображение результатов выполнения бизнес-операции CalcOrderTotalList

      private void CalcOrderTotalListCustomizeResultViewParameters(CustomizeResultViewParametersEventArgs e)

       {

          var businessOperation = (CalcOrderTotalList)e.BusinessOperation;

 

          var resultMsg = new StringBuilder();

           resultMsg.AppendLine(string.Format("Общая стоимость заказов составляет {0}", businessOperation.Total));

           resultMsg.AppendLine();

           resultMsg.AppendLine("Обработанные заказы:");

          foreach (var order in businessOperation.OrderList)

               resultMsg.AppendLine(order);

 

           MessageObject.CreateMessageInfo(

               e.ShowViewParameters,

               Application,

              "Результат",

               resultMsg.ToString()

               );

       }

 

 

      private static readonly string CalcOrderTotalListId = BusinessOperationBase.GetId(typeof(CalcOrderTotalList));

 

      // Кастомное отображение результатов выполнения бизнес-операций.

      // Для демонстрации возможностей, обработчик подписан на события для всех бизнес-операций.

      // Требуемая бизнес-операция определяется прямо в коде данного обработчика событий.

      private void CustomizeResultViewParameters(object sender, CustomizeResultViewParametersEventArgs e)

       {

          if (e.Method != BusinessOperationMethod.Execute)

              return; // Отображение результатов работы других методов БО не предполагается.

 

          // Требуемую бизнес-операцию можно определить как по типу экземпляра, так и по ее идентификатору.

          if (e.BusinessOperation.Id == CalcOrderTotalListId)

               CalcOrderTotalListCustomizeResultViewParameters(e);

          else if (e.BusinessOperation is ChangeFreightContext)

               ChangeFreightContextCustomizeResultViewParameters(e);

       }

 

      // Кастомное создание экземпляра объекта бизнес-операции.

      // Пример служит просто для демонтсрации такой возможности.

      private void CreateCustomChangeFreightContextInstance(object sender,

          CreateCustomBusinessOperationInstanceEventArgs e)

       {

          // При создании можно использовать любой требуемый конструктор.

           e.BusinessOperationInstance = new ChangeFreightContext();

       }

 

      // Кастомный запуск бизнес-операции ReversibleOperation с запросом на подтверждение запуска.

      private void ReversibleOperationCustomExecute(object sender, BusinessOperationExecuteEventArgs e)

       {

          var businessOperation = (ReversibleOperation)e.BusinessOperation;

 

          var msg = e.Method == BusinessOperationMethod.Execute

                         ? string.Format("Выполнить бизнес-операцию '{0}'?", businessOperation.Name)

                         : string.Format("Откатить бизнес-операцию '{0}'?", businessOperation.Name);

 

           ConfirmationMessage.Create(e.ShowViewParameters, Application, "Подтвердите", msg);

          var dialogController = e.ShowViewParameters.Controllers.OfType<DialogController>().First();

          var runner = BOMethodRunner.Create(Application, e.Method);

           dialogController.Accepting +=

             (s, args) => runner.Run((BOExecViewController)sender, businessOperation, args.ShowViewParameters);

 

           e.Handled = true;

       }

 

      // Кастомный запуск бизнес-операции ChangeFreightContext. Не взирая на то, что БО является управляемой, запускаем

      // ее как обычную, причем синхронно.

      // По завершению отображаются результаты (см. обработчик CustomizeResultViewParameters).

      private void ChangeFreightContextCustomExecute(object sender, BusinessOperationExecuteEventArgs e)

       {

          var businessOperation = (ChangeFreightContext)e.BusinessOperation;

 

          if (e.Method != BusinessOperationMethod.Execute)

              return;

 

          var dpo = BODynamicPropertiesObject.CreateWithParametersOf(businessOperation, BOParameterType.In);

           e.ShowViewParameters.CreatedView = dpo.CreateDetailView(Application.CreateObjectSpace(), Application, true);

          var dialogController = Application.CreateController<DialogController>();

 

          // Можно самостоятельно контролировать запуск бизнес-операции. В этом случае, после ее выполнения,

          // необходимо вызывать метод BOExecViewController.CreateResultViewParameters для поддержки возможности

          // формировать представления для отображения результатов.

           dialogController.Accepting += (s, args) =>

           {

               businessOperation.Execute();

               ((BOExecViewController)sender).CreateResultViewParameters(e.Method, businessOperation,

                 args.ShowViewParameters);

           };

           e.ShowViewParameters.Controllers.Add(dialogController);

           e.ShowViewParameters.CreatedView.Caption =

            string.Format("Кастомный интерфейс ввода параметров бизнес-операции {0}", businessOperation.Name);

           e.ShowViewParameters.TargetWindow = TargetWindow.NewModalWindow;

           e.ShowViewParameters.Context = TemplateContext.PopupWindow;

           e.ShowViewParameters.CreateAllControllers = true;

 

          // Актуально для Web. В Win свойство фрэймоворком игнорируется.

           ((DetailView)e.ShowViewParameters.CreatedView).ViewEditMode = ViewEditMode.Edit;

 

          // Другой способ выполнить бизнес-операцию - воспользоваться библиотечным классом.

          // В этом случае не нужно указывать свой обработчик для dalogController.Accepting.

          // BOMethodRunner, обнаружив, что в e.ShowViewParameters.CreatedView была указана пользовательская View,

          // создаст такой обработчик самостоятельно и

          // выполнит бизнес-операцию стандартным способом.

          //

          // var runner = BOMethodRunner.Create(Application, e.Method);

          // runner.Run(controller, businessOperation, e.ShowViewParameters);

 

           e.Handled = true;

       }

 

      private void ChangeFreightContextCustomizeResultViewParameters(CustomizeResultViewParametersEventArgs e)

       {

          var businessOperation = (ChangeFreightContext)e.BusinessOperation;

 

          var resultMsg = new StringBuilder();

          foreach (var order in businessOperation.ProcessedOrdersLog)

           {

               resultMsg.AppendLine(order);

           }

 

           MessageObject.CreateMessageInfo(

               e.ShowViewParameters,

               Application,

              "Обработанные заказы",

               resultMsg.ToString()

           );

       }

   }