XAF Win – Actions Placement in the Ribbon

When talking about actions placement we have a lot of choices. We can change the action container in the model or if doing it by code:

public class MyViewController : ViewController {
    public MyViewController() {
        SimpleAction myAction = new SimpleAction(this, "MyAction", "View");
        myAction.ImageName = "Action_SimpleAction";
    }
}

Here we can change the category (“View”) that map to that action container and that will be enough. We can also change the index inside the action container if we need a specific order. We can create a new Ribbon Template like shown here. A little cumbersome right? But what do we do if we want to have our action in a separate RibbonGroup and/or RibbonPage?

And of course we don’t want to create a new template. Here is where this ticket shines. All the info I am showing is covered in the ticket, I am just showing it in action and keeping a reference for myself.

We can use the controller below and taking care of everything in the model.

public class RibbonFromModelWithoutEventController : WindowController, IModelExtender
  {
      private IModelActions modelActions;

      void IModelExtender.ExtendModelInterfaces(ModelInterfaceExtenders extenders)
      {
          extenders.Add<IModelAction, IModelRibbonAction>();
      }
      protected override void OnActivated()
      {
          base.OnActivated();
          this.modelActions = Application.Model.ActionDesign.Actions;
          this.Application.CustomizeTemplate += this.Application_CustomizeTemplate;
      }

      protected override void OnDeactivated()
      {
          this.Application.CustomizeTemplate -= this.Application_CustomizeTemplate;
          this.modelActions = null;
          base.OnDeactivated();
      }
      private void Application_CustomizeTemplate(object sender, CustomizeTemplateEventArgs e)
      {
          RibbonForm ribbonForm = e.Template as RibbonForm;
          if (ribbonForm != null && ribbonForm.Ribbon is XafRibbonControlV2)
          {
              XafRibbonControlV2 ribbonControl = ribbonForm.Ribbon as XafRibbonControlV2;
              ribbonControl.BeginInit();
              foreach (IModelRibbonAction modelAction in modelActions.Select(action => action).Cast<IModelRibbonAction>().Where(a => !string.IsNullOrEmpty(a.TargetRibbonPage)))
              {
                  RibbonPage page = null;
                  page = ribbonControl.Pages.GetPageByText(modelAction.TargetRibbonPage);
                  if (page == null)
                  {
                      page = new RibbonPage(modelAction.TargetRibbonPage);
                      page.Name = modelAction.TargetRibbonPage;
                      ribbonControl.Pages.Add(page);
                  }

                  var group = page.Groups.GetGroupByText(modelAction.TargetRibbonGroup);
                  if (group == null)
                  {
                      var ribbonGroup = new RibbonPageGroup(modelAction.TargetRibbonGroup);
                      ribbonGroup.Name = modelAction.TargetRibbonGroup;
                      ribbonGroup.AllowTextClipping = false;
                      page.Groups.Add(ribbonGroup);

                      var barLinkContainerExItem = new BarLinkContainerExItem();
                      ribbonControl.Items.Add(barLinkContainerExItem);
                      ribbonGroup.ItemLinks.Add(barLinkContainerExItem);

                      var actionContainer = new BarLinkActionControlContainer();
                      actionContainer.BeginInit();
                      ribbonControl.ActionContainers.Add(actionContainer);
                      actionContainer.ActionCategory = modelAction.TargetRibbonGroup;
                      actionContainer.BarContainerItem = barLinkContainerExItem;
                      actionContainer.EndInit();
                  }
              }
              ribbonControl.EndInit();
          }
      }
  }

  public interface IModelRibbonAction : IModelAction
  {
      /// <summary>
      /// Gets or sets the target ribbon page.
      /// </summary>
      /// <value>The target ribbon page.</value>
      [Localizable(true)]
      string TargetRibbonPage { get; set; }

      /// <summary>
      /// Gets or sets the target ribbon group.
      /// </summary>
      /// <value>The target ribbon group.</value>
      [Localizable(true)]
      string TargetRibbonGroup { get; set; }

      /// <summary>
      /// Gets or sets the ribbon style.
      /// </summary>
      /// <value>The ribbon style.</value>
      RibbonItemStyles RibbonStyle { get; set; }
  }

It is really neat, it loops trough all actions where the TargetRibbonPage is not empty and it create a RibbonPage if it does not exist and then it does the same but with TargetRibbonGroup and RibbonGroup.

foreach (IModelRibbonAction modelAction in modelActions.Select(action => action).Cast<IModelRibbonAction>().Where(a => !string.IsNullOrEmpty(a.TargetRibbonPage)))
               {
                   RibbonPage page = null;
                   page = ribbonControl.Pages.GetPageByText(modelAction.TargetRibbonPage);
                   if (page == null)
                   {
                       page = new RibbonPage(modelAction.TargetRibbonPage);
                       page.Name = modelAction.TargetRibbonPage;
                       ribbonControl.Pages.Add(page);
                   }

                   var group = page.Groups.GetGroupByText(modelAction.TargetRibbonGroup);
                   if (group == null)
                   {
                       var ribbonGroup = new RibbonPageGroup(modelAction.TargetRibbonGroup);
                       ribbonGroup.Name = modelAction.TargetRibbonGroup;
                       ribbonGroup.AllowTextClipping = false;
                       page.Groups.Add(ribbonGroup);

                       var barLinkContainerExItem = new BarLinkContainerExItem();
                       ribbonControl.Items.Add(barLinkContainerExItem);
                       ribbonGroup.ItemLinks.Add(barLinkContainerExItem);

                       var actionContainer = new BarLinkActionControlContainer();
                       actionContainer.BeginInit();
                       ribbonControl.ActionContainers.Add(actionContainer);
                       actionContainer.ActionCategory = modelAction.TargetRibbonGroup;
                       actionContainer.BarContainerItem = barLinkContainerExItem;
                       actionContainer.EndInit();
                   }
               }

Let’s see the end result:

Here we have MyAction on the Home RibbonPage and View RibbonGroup,

Then we go to the model and set a new Page and a New Group:

And voila:

Source Code: https://github.com/jjcolumb/BlogDemo

Until next time, XAF out!

 

Posted in XAF

Leave a Reply

Your email address will not be published. Required fields are marked *