Business Operations. Executing Events and Customization

BOExecViewController and its Events

When the BO is started from the UI, the BOExecViewController class generates several events. To customize the BO, the developer can implement handlers for these events in order to control the following processes:

  • creating instances of a certain BO
  • initializing the BO parameters
  • starting the execution of the BO
  • generating the view that is displayed prior to the start of the BO and after its execution.

To subscribe events, use the BOExecViewController.BOEvents indexer property or the BOExecViewController instance. To subscribe for a particular BO, pass its Id or type as index. To subscribe for all BO, use the BOEvents property directly. To learn more, examine the event descriptions and code samples below.

CreateCustomBusinessOperationInstance

The event occurs when the BOExecViewController class needs to create a BO instance. The identifier of the required BO is passed as an argument. The event handler can create an instance of a BO class and set the argument's BusinessOperationInstance property to this instance. This event is provided by the BOEvents property.

BusinessOperationExecuting

The event occurs prior to the start of a BO. The arguments are:

  • the calling method (Execute or Rollback),
  • the object of the BO,
  • the ShowViewParameters class object.

You can initialize the ShowViewParameters object in the event handler for the fact it allows to set parameters (see Example 1 following the descriptions of the events in this page). The event handler can set the Cancel property to the "true" value that cancels the starting of the BO. In this case, the status of the ShowViewParameters object is important; this object will help to inform the user about the cancellation reason. This event is provided by the BOEvents property.

BusinessOperationCustomExecute

The event occurs when the controller needs to execute the BO. The arguments are:

  • the info on the calling method (Execute or Rollback),
  • the object of the BO,
  • the ShowViewParameters class object.

The event handler can call the required BO method on its own. To prevent the controller from starting the BO, the event handler should set the "true" value into the Handled property of the event argument.

Also it is necessary to arrange the BO parameters input (if there are any parameters) by initializing the fields of the ShowViewParameters object. When it is needed to display the result upon the completion of the BO, call the BOExecViewController.CreateResultViewParameters method and process the created ShowViewParameters object.

This event is provided by the BOEvents property.

CustomizeResultViewParameters

The event occurs after the BO execution. It is possible to initialize the fields of the ShowViewParameters object in order to display the results of the BO execution. The arguments are:

  • the info on the executed method (Execute or Rollback),
  • the object of the BO,
  • the ShowViewParameters class object.

This event is provided by the BOEvents property.

CustomizeContextBusinessOperationsList

The event is intended to manage the list of context BO. The argument contains this list that can be modified by the event handler. This event is provided by the BOExecViewController instance.

It is possible to subscribe for the events of the BOExecViewController class in custom controllers. The following examples show how to subscribe for the events and how to handle the events.

Example 1. Common Technique

The code snippet below demonstrates a common technique how to use BOExecViewController in custom code. The BusinessOperation class is fictitious and it used for demonstration.

  • c#
  • VB

/// <summary>
/// Example of custom handlers for Xafari.BC.BusinessOperations.Controllers.BOExecViewController events
/// </summary>
public class CustomizeBusinessOperationsController : ViewController
{
  private BOExecViewController _boExecViewController;
  protected override void OnActivated()
  {
    base.OnActivated();
    boExecViewController = Frame.GetController<BOExecViewController>();
    if (_boExecViewController != null)
    {
      // Subscribing to handling of controller's events for specific business operations.
      _boExecViewController.BOEvents[typeof(BusinessOperation)].BusinessOperationExecuting += BusinessOperationExecuting;
    }
  }
  protected override void OnDeactivated()
  {
    if (_boExecViewController != null)
    {
      _boExecViewController.BOEvents[typeof(BusinessOperation)].BusinessOperationExecuting -= BusinessOperationExecuting;
    }
    base.OnDeactivated();
  }
  // Custom BusinessOperation business operation executing.
  // Changes the view settings without changing the business operation method call.
  void BusinessOperationExecuting(object sender, BC.BusinessOperations.BusinessOperationExecutingEventArgs e)
  {
    e.ShowViewParameters.CreatedView = Application.CreateDetailView(Application.CreateObjectSpace(), ((BusinessOperation)e.BusinessOperation).Parameters);
    ((DetailView)e.ShowViewParameters.CreatedView).ViewEditMode = ViewEditMode.Edit;
    e.ShowViewParameters.TargetWindow = TargetWindow.NewModalWindow;
    e.ShowViewParameters.Context = TemplateContext.PopupWindow;
  }
}

''' <summary>
''' Example of custom handlers for Xafari.BC.BusinessOperations.Controllers.BOExecViewController events
''' </summary>
Public Class CustomizeBusinessOperationsController
  Inherits ViewController
  Private __boExecViewController As BOExecViewController
  Protected Overrides Sub OnActivated()
    MyBase.OnActivated()
    boExecViewController = Frame.GetController(Of BOExecViewController)()
    If __boExecViewController IsNot Nothing Then
      ' Subscribing to handling of controller's events for specific business operations.
      __boExecViewController.BOEvents(GetType(BusinessOperation)).BusinessOperationExecuting += BusinessOperationExecuting
    End If
  End Sub
  Protected Overrides Sub OnDeactivated()
    If __boExecViewController IsNot Nothing Then
      __boExecViewController.BOEvents(GetType(BusinessOperation)).BusinessOperationExecuting -= BusinessOperationExecuting
    End If
    MyBase.OnDeactivated()
  End Sub
  ' Custom BusinessOperation business operation executing.
  ' Changes the view settings without changing the business operation method call.
  Private Sub BusinessOperationExecuting(ByVal sender As Object, ByVal e As BC.BusinessOperations.BusinessOperationExecutingEventArgs)
    e.ShowViewParameters.CreatedView = Application.CreateDetailView(Application.CreateObjectSpace(), CType(e.BusinessOperation, BusinessOperation).Parameters)
    CType(e.ShowViewParameters.CreatedView, DetailView).ViewEditMode = ViewEditMode.Edit
    e.ShowViewParameters.TargetWindow = TargetWindow.NewModalWindow
    e.ShowViewParameters.Context = TemplateContext.PopupWindow
  End Sub
End Class

Example 2. Real-World Practice

This sections demonstrates CustomizeBusinessOperationsController View Controller that subscribes to various events of the Business Operations and handle these events.

Note

You can view the code used in this lesson in the Xafari.Northwind.DC.BusinessOperations|CustomizeBusinessOperationsController.cs file of the Northwind DC demo installed with Xafari. By default, the Northwind DC application is installed in %PUBLIC%\Documents\Xafari Framework vXX.X.XXXX Demos\Northwind.DC\.

  • c#
  • VB

/// <summary>
/// Example of custom handlers for Xafari.BC.BusinessOperations.Controllers.BOExecViewController events
/// </summary>
public class CustomizeBusinessOperationsController : ViewController
{
  private BOExecViewController _boExecViewController;
  protected override void OnActivated()
  {
    base.OnActivated();
    _boExecViewController = Frame.GetController<BOExecViewController>();
    if (_boExecViewController != null)
    {
      // Subscribing to handling of controller's events for specific business operations.
      _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[typeof(CalcOrderTotal)].ContextPropertyInitializing += CalcOrderTotalContextPropertyInitializing;
      _boExecViewController.BOEvents[typeof(CalcOrderTotal)].ProcessResult += CalcOrderTotalProcessResult;
      _boExecViewController.BOEvents[typeof(CalcOrderTotal)].BusinessOperationCustomExecute += CalcOrderTotalCustomExecute;
      // Subscribing to handling of controller's events for all business operations.
      _boExecViewController.BOEvents.ProcessResult += ProcessResult;
    }
  }
  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[typeof(CalcOrderTotal)].ContextPropertyInitializing -= CalcOrderTotalContextPropertyInitializing;
      _boExecViewController.BOEvents[typeof(CalcOrderTotal)].ProcessResult -= CalcOrderTotalProcessResult;
      _boExecViewController.BOEvents[typeof(CalcOrderTotal)].BusinessOperationCustomExecute -= CalcOrderTotalCustomExecute;
      _boExecViewController.BOEvents.ProcessResult -= ProcessResult;
    }
    base.OnDeactivated();
  }
  private const int BoundaryYear = 1996;
  // Before starting a business operation (in this case CalcOrderTotalList) you can change its parameters.
  // In this example, from the list of selected orders are deleted elements that do not meet a certain condition.
  // The situation is fictional, it used just to show the possibility of implementing something similar.
  // In the case of the order in the list, which is less than a year RequiredDate 1995, business operation
  // "Cost of orders (list)" won't performed, and an appropriate message will shown.
  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, Resources.Attention, Resources.CostOrderProhibited + Environment.NewLine + Resources.DeleteYouOrder + Environment.NewLine + Resources.SelectOtherOrders, BoundaryYear);
      e.Cancel = true;
    }
  }
  // Displaying the results of executing a business operation CalcOrderTotalList.
  private void CalcOrderTotalListProcessResult(ProcessResultEventArgs e)
  {
    var businessOperation = (CalcOrderTotalList)e.BusinessOperation;
    var resultMsg = new StringBuilder();
    resultMsg.AppendLine(string.Format(Resources.TotalValueOrder, businessOperation.Total));
    resultMsg.AppendLine();
    resultMsg.AppendLine(Resources.ProcessedOrders);
    foreach (var order in businessOperation.OrderList)
      resultMsg.AppendLine(order);
    MessageObject.CreateMessageInfo(e.ShowViewParameters, Application, Resources.Result, resultMsg.ToString());
  }
  private static readonly string CalcOrderTotalListId = BusinessOperationBase.GetId(typeof(CalcOrderTotalList));
  // Custom displaying the results of executing a business operation.
  // To demonstrate the possibilities, handler is subscribed to events for all business operations.
  // Required business operation is determined directly in the code of the event handler.
  private void ProcessResult(object sender, ProcessResultEventArgs e)
  {
    if (e.Method != BusinessOperationMethod.Execute)
      return; // Displaying the results of other methods of BO is not expected.
    // Preferred business operations can be defined either by type or by its ID.
    if (e.BusinessOperation.Id == CalcOrderTotalListId)
      CalcOrderTotalListProcessResult(e);
    else if (e.BusinessOperation is ChangeFreightContext)
      ChangeFreightContextProcessResult(e);
  }
  // Custom creation of instance of the business operation.
  // This example is used just to show the possibility of implementing something similar.
  private void CreateCustomChangeFreightContextInstance(object sender, CreateCustomBusinessOperationInstanceEventArgs e)
  {
    // Any desired constructor can be used.
    e.BusinessOperationInstance = new ChangeFreightContext();
  }
  // Custom initialization of business operation context property.
  // This example is used just to show the possibility of implementing something similar.
  private void CalcOrderTotalContextPropertyInitializing(object sender, ContextPropertyInitializingEventArgs e)
  {
    var currentObject = View.CurrentObject;
    // DataAccessMode = DataView behavior.
    var order = currentObject is XafDataViewRecord ? (Order)ObjectSpace.GetObject(currentObject) : (Order)currentObject;
    if (order.Number == "010248")
    {
      order = View.ObjectSpace.FindObject<Order>(CriteriaOperator.Parse("Number != '010248'"));
      if (order != null)
      {
        ((CalcOrderTotal)e.BusinessOperation).Order = order;
        e.Handled = true;
      }
    }
  }
  // Displaying the results of executing a business operation CalcOrderTotal.
  private void CalcOrderTotalProcessResult(object sender, ProcessResultEventArgs e)
  {
    var businessOperation = (CalcOrderTotal)e.BusinessOperation;
    var resultMsg = new StringBuilder();
    resultMsg.AppendLine(string.Format(Resources.OrderNumber, businessOperation.OrderNum));
    resultMsg.AppendLine(string.Format(Resources.DateOrder, businessOperation.OrderDate.ToShortDateString()));
    resultMsg.AppendLine(string.Format(Resources.TotalCostOrder, businessOperation.Total));
    MessageObject.CreateMessageInfo(e.ShowViewParameters, Application, Resources.Result, resultMsg.ToString());
  }
  // Custom executing of business operation CalcOrderTotal.
  // If business operation does not implement interface IBusinessOperationManaged, it is executed directly
  // in main thread of application unlike default behavior. Otherwise, it is used the default
  // way: business operation is executed as managed operation.
  private void CalcOrderTotalCustomExecute(object sender, BusinessOperationExecuteEventArgs e)
  {
    BOMethodRunner runner;
    if (e.Method == BusinessOperationMethod.Execute)
      runner = new CustomBOMethodRunnerExecute(Application);
    else
      runner = new CustomBOMethodRunnerRollback(Application);
    runner.Run(((BOExecViewController)sender).ProcessResult, e.BusinessOperation, e.ShowViewParameters);
    e.Handled = true;
  }
  // Custom executing of business operation ReversibleOperation with request for confirmation of the executing.
  private void ReversibleOperationCustomExecute(object sender, BusinessOperationExecuteEventArgs e)
  {
    var businessOperation = (ReversibleOperation)e.BusinessOperation;
    var msg = e.Method == BusinessOperationMethod.Execute ? string.Format(Resources.Execute, businessOperation.Name) : string.Format(Resources.Rollback, businessOperation.Name);
    ConfirmationMessage.Create(e.ShowViewParameters, Application, Resources.Confirm, msg);
    var dialogController = e.ShowViewParameters.Controllers.OfType<DialogController>().First();
    var runner = BOMethodRunner.Create(Application, e.Method);
    dialogController.Accepting += (s, args) => runner.Run(((BOExecViewController)sender).ProcessResult, businessOperation, args.ShowViewParameters);
    e.Handled = true;
  }
  // Custom executing of business operation ChangeFreightContext. It is executed synchronously.
  // After it finish, the results are displayed(see CustomizeResultViewParameters handler).
  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>();
    // You can control the launch of business operations. In this case, after the execution, you must call
    // the method BOExecViewController.CreateResultViewParameters to support the possibility of submission of view to display the results.
    dialogController.Accepting += (s, args) =>
    {
      businessOperation.Execute();
      ((BOExecViewController)sender).ProcessResult(e.Method, businessOperation, args.ShowViewParameters);
    };
    e.ShowViewParameters.Controllers.Add(dialogController);
    e.ShowViewParameters.CreatedView.Caption = string.Format(Resources.UserInterfaceParameter, businessOperation.Name);
    e.ShowViewParameters.TargetWindow = TargetWindow.NewModalWindow;
    e.ShowViewParameters.Context = TemplateContext.PopupWindow;
    e.ShowViewParameters.CreateAllControllers = true;
    ((DetailView)e.ShowViewParameters.CreatedView).ViewEditMode = ViewEditMode.Edit; // Actual for Web. Framework ignores this property at Win.
    // Another way to run a business operation - use the library classes. In this case, do not specify a handler for dalogController.Accepting.
    // BOMethodRunner, found that e.ShowViewParameters.CreatedView been specified custom View, create a self-handler and execute
    // the business operation at default mode.
    //
    // var runner = BOMethodRunner.Create(Application, e.Method);
    // runner.Run(controller, businessOperation, e.ShowViewParameters);
    e.Handled = true;
  }
  private void ChangeFreightContextProcessResult(ProcessResultEventArgs e)
  {
    var businessOperation = (ChangeFreightContext)e.BusinessOperation;
    var resultMsgBuilder = new StringBuilder();
    foreach (var order in businessOperation.ProcessedOrdersLog)
    {
      resultMsgBuilder.AppendLine(order);
    }
    var resultMsg = resultMsgBuilder.Length != 0 ? resultMsgBuilder.ToString() : Resources.NoOrdersMessage;
    MessageObject.CreateMessageInfo(e.ShowViewParameters, Application, Resources.ProcessedOrders, resultMsg);
  }
  private class CustomBOMethodRunnerExecute : BOMethodRunnerExecute
  {
    public CustomBOMethodRunnerExecute(XafApplication application)
      : base(application)
    {
    }
    protected override void RunOperationCore(BusinessOperationAction createResultViewParameters, IBusinessOperation businessOperation, ShowViewParameters showViewParameters)
    {
      if (businessOperation is IBusinessOperationManaged)
      {
        RunAsManagedOperation(createResultViewParameters, businessOperation, showViewParameters);
      }
      else
      {
        businessOperation.Execute();
        createResultViewParameters(Method, businessOperation, showViewParameters);
      }
    }
  }
  private class CustomBOMethodRunnerRollback : BOMethodRunnerRollback
  {
    public CustomBOMethodRunnerRollback(XafApplication application)
      : base(application)
    {
    }
    protected override void RunOperationCore(BusinessOperationAction createResultViewParameters, IBusinessOperation businessOperation, ShowViewParameters showViewParameters)
    {
      if (businessOperation is IBusinessOperationManaged)
      {
        RunAsManagedOperation(createResultViewParameters, businessOperation, showViewParameters);
      }
      else
      {
        businessOperation.Rollback();
        createResultViewParameters(Method, businessOperation, showViewParameters);
      }
    }
  }
}

''' <summary>
''' Example of custom handlers for Xafari.BC.BusinessOperations.Controllers.BOExecViewController events
''' </summary>
Public Class CustomizeBusinessOperationsController
  Inherits ViewController
  Private __boExecViewController As BOExecViewController
  Protected Overrides Sub OnActivated()
    MyBase.OnActivated()
    __boExecViewController = Frame.GetController(Of BOExecViewController)()
    If __boExecViewController IsNot Nothing Then
      ' Subscribing to handling of controller's events for specific business operations.
      __boExecViewController.BOEvents(GetType(CalcOrderTotalList)).BusinessOperationExecuting += CalcOrderTotalListExecuting
      __boExecViewController.BOEvents(GetType(ReversibleOperation)).BusinessOperationCustomExecute += ReversibleOperationCustomExecute
      __boExecViewController.BOEvents(GetType(ChangeFreightContext)).BusinessOperationCustomExecute += ChangeFreightContextCustomExecute
      __boExecViewController.BOEvents(GetType(ChangeFreightContext)).CreateCustomBusinessOperationInstance += CreateCustomChangeFreightContextInstance
      __boExecViewController.BOEvents(GetType(CalcOrderTotal)).ContextPropertyInitializing += CalcOrderTotalContextPropertyInitializing
      __boExecViewController.BOEvents(GetType(CalcOrderTotal)).ProcessResult += CalcOrderTotalProcessResult
      __boExecViewController.BOEvents(GetType(CalcOrderTotal)).BusinessOperationCustomExecute += CalcOrderTotalCustomExecute
      ' Subscribing to handling of controller's events for all business operations.
      __boExecViewController.BOEvents.ProcessResult += ProcessResult
    End If
  End Sub
  Protected Overrides Sub OnDeactivated()
    If __boExecViewController IsNot Nothing Then
      __boExecViewController.BOEvents(GetType(CalcOrderTotalList)).BusinessOperationExecuting -= CalcOrderTotalListExecuting
      __boExecViewController.BOEvents(GetType(ReversibleOperation)).BusinessOperationCustomExecute -= ReversibleOperationCustomExecute
      __boExecViewController.BOEvents(GetType(ChangeFreightContext)).BusinessOperationCustomExecute -= ChangeFreightContextCustomExecute
      __boExecViewController.BOEvents(GetType(ChangeFreightContext)).CreateCustomBusinessOperationInstance -= CreateCustomChangeFreightContextInstance
      __boExecViewController.BOEvents(GetType(CalcOrderTotal)).ContextPropertyInitializing -= CalcOrderTotalContextPropertyInitializing
      __boExecViewController.BOEvents(GetType(CalcOrderTotal)).ProcessResult -= CalcOrderTotalProcessResult
      __boExecViewController.BOEvents(GetType(CalcOrderTotal)).BusinessOperationCustomExecute -= CalcOrderTotalCustomExecute
      __boExecViewController.BOEvents.ProcessResult -= ProcessResult
    End If
    MyBase.OnDeactivated()
  End Sub
  Private Const _BoundaryYear As Integer = 1996
  ' Before starting a business operation (in this case CalcOrderTotalList) you can change its parameters.
  ' In this example, from the list of selected orders are deleted elements that do not meet a certain condition.
  ' The situation is fictional, it used just to show the possibility of implementing something similar.
  ' In the case of the order in the list, which is less than a year RequiredDate 1995, business operation
  ' "Cost of orders (list)" won't performed, and an appropriate message will shown.
  Private Sub CalcOrderTotalListExecuting(ByVal sender As Object, ByVal e As BusinessOperationExecutingEventArgs)
    Dim businessOperation = CType(e.BusinessOperation, CalcOrderTotalList)
    businessOperation.Orders.RemoveAll(Function(ByVal order) order.RequiredDate.Year < _BoundaryYear)
    If businessOperation.Orders.Count = 0 Then
      MessageObject.CreateMessageWarning(e.ShowViewParameters, Application, Resources.Attention, Resources.CostOrderProhibited + Environment.NewLine + Resources.DeleteYouOrder + Environment.NewLine + Resources.SelectOtherOrders, _BoundaryYear)
      e.Cancel = True
    End If
  End Sub
  ' Displaying the results of executing a business operation CalcOrderTotalList.
  Private Sub CalcOrderTotalListProcessResult(ByVal e As ProcessResultEventArgs)
    Dim businessOperation = CType(e.BusinessOperation, CalcOrderTotalList)
    Dim resultMsg = New StringBuilder()
    resultMsg.AppendLine(String.Format(Resources.TotalValueOrder, businessOperation.Total))
    resultMsg.AppendLine()
    resultMsg.AppendLine(Resources.ProcessedOrders)
    For Each order In businessOperation.OrderList
      resultMsg.AppendLine(order)
    Next
    MessageObject.CreateMessageInfo(e.ShowViewParameters, Application, Resources.Result, resultMsg.ToString())
  End Sub
  Private Shared ReadOnly _CalcOrderTotalListId As String = BusinessOperationBase.GetId(GetType(CalcOrderTotalList))
  ' Custom displaying the results of executing a business operation.
  ' To demonstrate the possibilities, handler is subscribed to events for all business operations.
  ' Required business operation is determined directly in the code of the event handler.
  Private Sub ProcessResult(ByVal sender As Object, ByVal e As ProcessResultEventArgs)
    If e.Method <> BusinessOperationMethod.Execute Then
      Return
    End If ' Displaying the results of other methods of BO is not expected.
    ' Preferred business operations can be defined either by type or by its ID.
    If e.BusinessOperation.Id = _CalcOrderTotalListId Then
      CalcOrderTotalListProcessResult(e)
    Else
      If TypeOf e.BusinessOperation Is ChangeFreightContext Then
        ChangeFreightContextProcessResult(e)
      End If
    End If
  End Sub
  ' Custom creation of instance of the business operation.
  ' This example is used just to show the possibility of implementing something similar.
  Private Sub CreateCustomChangeFreightContextInstance(ByVal sender As Object, ByVal e As CreateCustomBusinessOperationInstanceEventArgs)
    ' Any desired constructor can be used.
    e.BusinessOperationInstance = New ChangeFreightContext()
  End Sub
  ' Custom initialization of business operation context property.
  ' This example is used just to show the possibility of implementing something similar.
  Private Sub CalcOrderTotalContextPropertyInitializing(ByVal sender As Object, ByVal e As ContextPropertyInitializingEventArgs)
    Dim currentObject = View.CurrentObject
    ' DataAccessMode = DataView behavior.
    Dim order = If(TypeOf currentObject Is XafDataViewRecord, CType(ObjectSpace.GetObject(currentObject), Order), CType(currentObject, Order))
    If order.Number = "010248" Then
      order = View.ObjectSpace.FindObject(Of Order)(CriteriaOperator.Parse("Number != '010248'"))
      If order IsNot Nothing Then
        CType(e.BusinessOperation, CalcOrderTotal).Order = order
        e.Handled = True
      End If
    End If
  End Sub
  ' Displaying the results of executing a business operation CalcOrderTotal.
  Private Sub CalcOrderTotalProcessResult(ByVal sender As Object, ByVal e As ProcessResultEventArgs)
    Dim businessOperation = CType(e.BusinessOperation, CalcOrderTotal)
    Dim resultMsg = New StringBuilder()
    resultMsg.AppendLine(String.Format(Resources.OrderNumber, businessOperation.OrderNum))
    resultMsg.AppendLine(String.Format(Resources.DateOrder, businessOperation.OrderDate.ToShortDateString()))
    resultMsg.AppendLine(String.Format(Resources.TotalCostOrder, businessOperation.Total))
    MessageObject.CreateMessageInfo(e.ShowViewParameters, Application, Resources.Result, resultMsg.ToString())
  End Sub
  ' Custom executing of business operation CalcOrderTotal.
  ' If business operation does not implement interface IBusinessOperationManaged, it is executed directly
  ' in main thread of application unlike default behavior. Otherwise, it is used the default
  ' way: business operation is executed as managed operation.
  Private Sub CalcOrderTotalCustomExecute(ByVal sender As Object, ByVal e As BusinessOperationExecuteEventArgs)
    Dim runner As BOMethodRunner
    If e.Method = BusinessOperationMethod.Execute Then
      runner = New CustomBOMethodRunnerExecute(Application)
    Else
      runner = New CustomBOMethodRunnerRollback(Application)
    End If
    runner.Run(CType(sender, BOExecViewController).ProcessResult, e.BusinessOperation, e.ShowViewParameters)
    e.Handled = True
  End Sub
  ' Custom executing of business operation ReversibleOperation with request for confirmation of the executing.
  Private Sub ReversibleOperationCustomExecute(ByVal sender As Object, ByVal e As BusinessOperationExecuteEventArgs)
    Dim businessOperation = CType(e.BusinessOperation, ReversibleOperation)
    Dim msg = If(e.Method = BusinessOperationMethod.Execute, String.Format(Resources.Execute, businessOperation.Name), String.Format(Resources.Rollback, businessOperation.Name))
    ConfirmationMessage.Create(e.ShowViewParameters, Application, Resources.Confirm, msg)
    Dim dialogController = e.ShowViewParameters.Controllers.OfType(Of DialogController)().First()
    Dim runner = BOMethodRunner.Create(Application, e.Method)
    dialogController.Accepting += Function(ByVal s, ByVal args) runner.Run(CType(sender, BOExecViewController).ProcessResult, businessOperation, args.ShowViewParameters)
    e.Handled = True
  End Sub
  ' Custom executing of business operation ChangeFreightContext. It is executed synchronously.
  ' After it finish, the results are displayed(see CustomizeResultViewParameters handler).
  Private Sub ChangeFreightContextCustomExecute(ByVal sender As Object, ByVal e As BusinessOperationExecuteEventArgs)
    Dim businessOperation = CType(e.BusinessOperation, ChangeFreightContext)
    If e.Method <> BusinessOperationMethod.Execute Then
      Return
    End If
    Dim dpo = BODynamicPropertiesObject.CreateWithParametersOf(businessOperation, BOParameterType.[In])
    e.ShowViewParameters.CreatedView = dpo.CreateDetailView(Application.CreateObjectSpace(), Application, True)
    Dim dialogController = Application.CreateController(Of DialogController)()
    ' You can control the launch of business operations. In this case, after the execution, you must call
    ' the method BOExecViewController.CreateResultViewParameters to support the possibility of submission of view to display the results.
    dialogController.Accepting += Sub(ByVal s, ByVal args)
      businessOperation.Execute()
      CType(sender, BOExecViewController).ProcessResult(e.Method, businessOperation, args.ShowViewParameters)
    End Sub
    e.ShowViewParameters.Controllers.Add(dialogController)
    e.ShowViewParameters.CreatedView.Caption = String.Format(Resources.UserInterfaceParameter, businessOperation.Name)
    e.ShowViewParameters.TargetWindow = TargetWindow.NewModalWindow
    e.ShowViewParameters.Context = TemplateContext.PopupWindow
    e.ShowViewParameters.CreateAllControllers = True
    CType(e.ShowViewParameters.CreatedView, DetailView).ViewEditMode = ViewEditMode.Edit ' Actual for Web. Framework ignores this property at Win.
    ' Another way to run a business operation - use the library classes. In this case, do not specify a handler for dalogController.Accepting.
    ' BOMethodRunner, found that e.ShowViewParameters.CreatedView been specified custom View, create a self-handler and execute
    ' the business operation at default mode.
    '
    ' var runner = BOMethodRunner.Create(Application, e.Method);
    ' runner.Run(controller, businessOperation, e.ShowViewParameters);
    e.Handled = True
  End Sub
  Private Sub ChangeFreightContextProcessResult(ByVal e As ProcessResultEventArgs)
    Dim businessOperation = CType(e.BusinessOperation, ChangeFreightContext)
    Dim resultMsgBuilder = New StringBuilder()
    For Each order In businessOperation.ProcessedOrdersLog
      resultMsgBuilder.AppendLine(order)
    Next
    Dim resultMsg = If(resultMsgBuilder.Length <> 0, resultMsgBuilder.ToString(), Resources.NoOrdersMessage)
    MessageObject.CreateMessageInfo(e.ShowViewParameters, Application, Resources.ProcessedOrders, resultMsg)
  End Sub
  Private Class CustomBOMethodRunnerExecute
    Inherits BOMethodRunnerExecute
    Public Sub New(ByVal application As XafApplication)
      MyBase.New(application)
    End Sub
    Protected Overrides Sub RunOperationCore(ByVal createResultViewParameters As BusinessOperationAction, ByVal businessOperation As IBusinessOperation, ByVal showViewParameters As ShowViewParameters)
      If TypeOf businessOperation Is IBusinessOperationManaged Then
        RunAsManagedOperation(createResultViewParameters, businessOperation, showViewParameters)
      Else
        businessOperation.Execute()
        createResultViewParameters(Method, businessOperation, showViewParameters)
      End If
    End Sub
  End Class
  Private Class CustomBOMethodRunnerRollback
    Inherits BOMethodRunnerRollback
    Public Sub New(ByVal application As XafApplication)
      MyBase.New(application)
    End Sub
    Protected Overrides Sub RunOperationCore(ByVal createResultViewParameters As BusinessOperationAction, ByVal businessOperation As IBusinessOperation, ByVal showViewParameters As ShowViewParameters)
      If TypeOf businessOperation Is IBusinessOperationManaged Then
        RunAsManagedOperation(createResultViewParameters, businessOperation, showViewParameters)
      Else
        businessOperation.Rollback()
        createResultViewParameters(Method, businessOperation, showViewParameters)
      End If
    End Sub
  End Class
End Class