Exercise 1: Customizing Office with Ribbons and Backstage
Exercise 1: Customizing Office with Ribbons and Backstage

Backstage is a perfect place to put UI elements that take up space but are not necessary when actively editing the document. In this case you will be using Backstage and a Ribbon together to create multiple parts of a complete add-in.

Task 1 – Add Export Backstage tab

In this first task, you will create a new Backstage tab named Export to manage the quick export functionality.

  1. Add a new XML Ribbon item to the existing ExportAddIn project
    1. Open VisualStudio 2010 and open the starter lab at C:\Office2010DeveloperTrainingKit\Labs\OfficeUI\Source\[language]\Starter\ExportAddIn\ExportAddIn.sln
    2. Right click ExportAddIn in the Solution Explorer and choose Add -> New Item.
    3. In the Add New Item dialog, select the Office category.
    4. Choose the Ribbon (XML) item type and enter a name of Ribbon.vb(in case of VB) & Ribbon.cs(in case of C#)
    5. Click Add to create the new ribbon
    6. Figure 1(a)-In case of C#
      Add Ribbon (XML) Item

    7. Figure 1(b)-In case of VB
      Add Ribbon (XML) Item


    8. Open the Ribbon.xml file located in the Solution Explorer
  2. Add XML Markup to the Ribbon.xml file to define the Export Backstage tab
    1. Remove the current ribbon node from the Ribbon.xml file
    2. Add the following markup to define the Backstage tab and the first column of information
      XMLCopy Code
      <backstage>  
        <tab id="tabExport" label="Export" insertAfterMso="TabInfo">
          <firstColumn>
          </firstColumn>  
        </tab>
      </backstage>
      

    3. Inside the firstColumn element, add the following markup to define the group containing the XPS export controls
      XMLCopy Code
      <group id="grpExportXPS" label="Export as XPS" 
             helperText="Exports the current document as XPS.">
        <primaryItem>
          <button id="btnBackStageXPS" label="To XPS" 
                  getImage="GetButtonImage" />
        </primaryItem>  
        <topItems>
          <checkBox id="chkEnableXPS" label="Allow XPS Export" />  
          <editBox id="txtXPSPath" label="Export Path"  
                   sizeString="WWWWWWWWWWWWWWWWWWWWWWWWWWWWWW" />
        </topItems>
      </group>
      
    4. Note:
      The XPS output controls are made up of a button to perform the export, a check box to enable or disable exporting to XPS and a edit box to define the filename of the exported file.


    5. Immediately following the previous group, add the following markup to define the PDF export controls
      XMLCopy Code
      <group id="grpExportPDF" label="Export as PDF" 
             helperText="Exports the current document as PDF.">
        <primaryItem>
          <button id="btnBackStagePDF" label="To PDF" 
                  getImage="GetButtonImage" />
        </primaryItem>  
        <topItems>
          <checkBox id="chkEnablePDF" label="Allow PDF Export" />  
          <editBox id="txtPDFPath" label="Export Path"  
                   sizeString="WWWWWWWWWWWWWWWWWWWWWWWWWWWWWW" />
        </topItems>
      </group>
      

  3. Define the code that will load images for the export buttons
    1. Open Ribbon.vb(in case of VB) & Ribbon.cs(in case of C#) by double clicking it in the Solution Explorer
    2. Add the following GetButtonImage method to the Ribbon class
      C#Copy Code
      public System.Drawing.Bitmap GetButtonImage(
        Office.IRibbonControl control)
      {
          switch (control.Id)
          {                
              case "btnBackStageXPS":
                  return Properties.Resources.XPS;
              case "btnBackStagePDF":
                  return Properties.Resources.PDF;
              default:
                  return null;
          }
      }
      
      Visual BasicCopy Code
      Public Function GetButtonImage(ByVal control As Office.IRibbonControl) As System.Drawing.Bitmap
      Select Case control.Id
      Case "btnBackStageXPS"
      Return My.Resources.XPS
      Case "btnBackStagePDF"
      Return My.Resources.PDF
      Case Else
      Return Nothing
      End Select
      End Function
      
    3. Note:
      The getImage attribute in the button elements define a public method Office will call any time a button loads. This method uses a switch command to differentiate between the different buttons.


  4. Override the CreateRibbonExtensibilityObject method in the add-in to define the ribbon to load
    1. Open the ThisAddIn class by double clicking it in the Solution Explorer
    2. In the ThisAddIn class, override the CreateRibbonExtensibilityObject method and return a new Ribbon object
      C#Copy Code
      protected override 
        Office.IRibbonExtensibility CreateRibbonExtensibilityObject()
      {
          return new Ribbon();
      }
      
      Visual BasicCopy Code
      Protected Overrides Function CreateRibbonExtensibilityObject() As Office.IRibbonExtensibility
      Return New Ribbon()
      End Function
      

  5. Run the add-in and verify the Backstage tab looks correct
    1. In the Debug menu, click Start Without Debugging
    2. Once Word 2010 loads, click the Backstage button (labeled as File)
    3. In Backstage switch to the Export tab and verify it looks like the image below

      Figure 2
      Custom Backstage Export tab

Task 2 – Connect Backstage tab to document properties

In this task, you will connect the controls in the Export tab to the CustomDocumentProperties object in the active document. This will allow the state of the controls to be persisted in the document and loaded when the document is loaded later.

  1. Define the code behind that will determine when the button and editBox controls are enabled
    1. Open Ribbon.xml by double clicking it in the SolutionExplorer
    2. Add a getEnabled attribute to the button and editBox controls
      XMLCopy Code
      <button id="btnBackStageXPS" 
        getEnabled="GetEnable"
        ... />
      
    3. Note:
      You should find 2 button controls and 2 editBox controls


    4. Open Ribbon.vb(in case of VB) & Ribbon.cs(in case of C#) by double clicking it in the Solution Explorer
    5. Add the following private field to the class
      C#Copy Code
      private ExportProperties m_properties = new ExportProperties();
      
      Visual BasicCopy Code
      Private m_properties As New ExportProperties()
      
    6. Note:
      The ExportProperties class is a wrapper provided for you that wraps the CustomDocumentProperties collection of the current ActiveDocument.


    7. Create a GetEnable method to determine the enable state of other controls.
      C#Copy Code
      public bool GetEnable(Office.IRibbonControl control)
      {
          switch (control.Id)
          {
              case "btnBackStageXPS":
              case "txtXPSPath":
                  return m_properties.XpsEnabled;
              case "btnBackStagePDF":
              case "txtPDFPath":
                  return m_properties.PdfEnabled;
              default:
                  return false;
          }
      }
      
      Visual BasicCopy Code
      Public Function GetEnable(ByVal control As Office.IRibbonControl) As Boolean
      Select Case control.Id
      Case "btnBackStageXPS", "txtXPSPath"
      Return m_properties.XpsEnabled
      Case "btnBackStagePDF", "txtPDFPath"
      Return m_properties.PdfEnabled
      Case Else
      Return False
      End Select
      End Function
      

  2. Add code to populate and respond to events from the enabled checkboxes
    1. Open Ribbon.xml by double clicking it in the SolutionExplorer
    2. Add a getPressed and onAction attribute to every checkBox element in the Backstage markup
      XMLCopy Code
      <checkBox id="chkEnablePDF" 
        getPressed="IsEnableChecked" 
        onAction="EnableChecked" 
        .../>
      
    3. Note:
      You should find 2 checkBox controls


    4. Open Ribbon.vb(in case of VB) & Ribbon.cs(in case of C#) by double clicking it in the Solution Explorer
    5. Create an IsEnableChecked method that will respond to requests from check box controls to get their current state
      C#Copy Code
      public bool IsEnableChecked(Office.IRibbonControl control)
      {
          if (control.Id == "chkEnableXPS")
              return m_properties.XpsEnabled;
          else if (control.Id == "chkEnablePDF")
              return m_properties.PdfEnabled;
          else
              return false;
      }
      
      Visual BasicCopy Code
      Public Function IsEnableChecked(ByVal control As Office.IRibbonControl) As Boolean
      If control.Id = "chkEnableXPS" Then
      Return m_properties.XpsEnabled
      ElseIf control.Id = "chkEnablePDF" Then
      Return m_properties.PdfEnabled
      Else
      Return False
      End If
      End Function
      

    6. Create an EnableChecked method that will respond to the checking of a check box
      C#Copy Code
      public void EnableChecked(Office.IRibbonControl control, bool value)
      {
          if (control.Id == "chkEnableXPS")
          {
              m_properties.XpsEnabled = value;
              ribbon.InvalidateControl("btnBackStageXPS");
              ribbon.InvalidateControl("txtXPSPath");
          }
          else if (control.Id == "chkEnablePDF")
          {
              m_properties.PdfEnabled = value;
              ribbon.InvalidateControl("btnBackStagePDF");
              ribbon.InvalidateControl("txtPDFPath");
          }
      }
      
      Visual BasicCopy Code
      Public Sub EnableChecked(ByVal control As Office.IRibbonControl, ByVal value As Boolean)
      If control.Id = "chkEnableXPS" Then
      m_properties.XpsEnabled = value
      ribbon.InvalidateControl("btnBackStageXPS")
      ribbon.InvalidateControl("txtXPSPath")
      ElseIf control.Id = "chkEnablePDF" Then
      m_properties.PdfEnabled = value
      ribbon.InvalidateControl("btnBackStagePDF")
      ribbon.InvalidateControl("txtPDFPath")
      End If
      End Sub
      
    7. Note:
      The calls to ribbon.InvalidateControl force those controls to reevaluate their state. This will lead to another call to GetEnabled that will now have a different result.


  3. Add code to populate and respond to events from the path edit boxes
    1. Open Ribbon.xml by double clicking it in the SolutionExplorer
    2. Add a getText and onChange attribute to every editBox element
      XMLCopy Code
      <editBox id="txtPDFPath"
        getText="GetExportPath" 
        onChange="SetExportPath" 
        ... />
      
    3. Note:
      You should find 2 editBox controls


    4. Open Ribbon.vb(in case of VB) & Ribbon.cs(in case of C#) by double clicking it in the Solution Explorer
    5. Create a GetExportPath method that will retrieve the current export path for the editBox controls
      C#Copy Code
      public string GetExportPath(Office.IRibbonControl control)
      {
          if (control.Id == "txtXPSPath")
              return m_properties.XpsExportPath;
          else if (control.Id == "txtPDFPath")
              return m_properties.PdfExportPath;
          else
              return string.Empty;           
      }
      
      Visual BasicCopy Code
      Public Function GetExportPath(ByVal control As Office.IRibbonControl) As String
      If control.Id = "txtXPSPath" Then
      Return m_properties.XpsExportPath
      ElseIf control.Id = "txtPDFPath" Then
      Return m_properties.PdfExportPath
      Else
      Return String.Empty
      End If
      End Function
      

    6. Create a SetExportPath method that will respond to the change event of the editBox control
      C#Copy Code
      public void SetExportPath(Office.IRibbonControl control, string value)
      {
          if (control.Id == "txtXPSPath")
              m_properties.XpsExportPath = value;
          else if (control.Id == "txtPDFPath")
              m_properties.PdfExportPath = value;
      }
      
      Visual BasicCopy Code
      Public Sub SetExportPath(ByVal control As Office.IRibbonControl, ByVal value As String)
      If control.Id = "txtXPSPath" Then
      m_properties.XpsExportPath = value
      ElseIf control.Id = "txtPDFPath" Then
      m_properties.PdfExportPath = value
      End If
      End Sub
      

  4. Run the add-in and verify the enable checkboxes work
    1. In the Debug menu, click Start Without Debugging
    2. Once Word 2010 loads, click the Backstage button (labeled as File)
    3. In Backstage switch to the Export tab
    4. Check and uncheck the enabled checkboxes and verify the related controls are enabled and disabled

      Figure 1
      Enable check box in Backstage tab

Task 3 – Add quick export buttons to the Home ribbon tab

In this task, you will add a Quick Export ribbon button to the Home ribbon tab. It will tie into the same functionality as the buttons on Backstage.

  1. Add the ribbon markup to the Ribbon.xml file
    1. Open Ribbon.xml by double clicking it in the SolutionExplorer
    2. Add the markup that will create a new Quick Export group in the Home tab
      1. Make sure the ribbon xml element is added before the backstage xml element
        XMLCopy Code
        <ribbon>  
          <tabs>
            <tab idMso="TabHome">  
              <group id="grpQuickExport" autoScale="true">
              </group>
            </tab>  
          </tabs>
        </ribbon>
        
    3. Note:
      The use of the idMso attribute tells Office to put the following group in the existing tab.


    4. Inside the grpQuickExport group element, add a menu control using an existing image within Office
      XMLCopy Code
      <menu id="btnQuickExport" size="large" itemSize="large" 
            label="Quick Export" imageMso="PageMenu" >
      </menu>
      
    5. Note:
      The use of imageMso tells Office to use an built in Office image


    6. Inside the menu element, add the two button controls to perform the export as XPS or PDF
      XMLCopy Code
      <button id="btnRibbonXPS" label="XPS" getEnabled="GetEnable" 
              getImage="GetButtonImage" />
      <button id="btnRibbonPDF" label="PDF" getEnabled="GetEnable" 
              getImage="GetButtonImage" />
      

  2. Update the code behind to update the Ribbon buttons as well as the Backstage buttons
    1. Open Ribbon.vb(in case of VB) & Ribbon.cs(in case of C#) by double clicking it in the Solution Explorer
    2. Locate the GetButtonImage method and add cases for the ribbon buttons
      C#Copy Code
      case "btnRibbonXPS":
      case "btnBackStageXPS":
          return Properties.Resources.XPS;
      case "btnRibbonPDF":
      case "btnBackStagePDF":
          return Properties.Resources.PDF;
      
      Visual BasicCopy Code
      Case "btnRibbonXPS", "btnBackStageXPS"
      Return My.Resources.XPS
      Case "btnRibbonPDF", "btnBackStagePDF"
      Return My.Resources.PDF
      

    3. Locate the GetEnable method and add cases for the ribbon buttons
      C#Copy Code
      case "btnRibbonXPS":
      case "btnBackStageXPS":
      case "txtXPSPath":
          return m_properties.XpsEnabled;
      case "btnRibbonPDF":
      case "btnBackStagePDF":
      case "txtPDFPath":
          return m_properties.PdfEnabled;
      
      Visual BasicCopy Code
      Case "btnRibbonXPS", "btnBackStageXPS", "txtXPSPath"
      Return m_properties.XpsEnabled
      Case "btnRibbonPDF", "btnBackStagePDF", "txtPDFPath"
      Return m_properties.PdfEnabled
      

    4. Locate the EnableChecked method and add InvalidateControl calls for the ribbon buttons
      C#Copy Code
      if (control.Id == "chkEnableXPS")
      {
          m_properties.XpsEnabled = value;
      ribbon.InvalidateControl("btnRibbonXPS");
          ribbon.InvalidateControl("btnBackStageXPS");
          ribbon.InvalidateControl("txtXPSPath");
      }
      else if (control.Id == "chkEnablePDF")
      {
          m_properties.PdfEnabled = value;
          ribbon.InvalidateControl("btnRibbonPDF"); 
          ribbon.InvalidateControl("btnBackStagePDF");
          ribbon.InvalidateControl("txtPDFPath");
      }
      
      Visual BasicCopy Code
      If control.Id = "chkEnableXPS" Then
      m_properties.XpsEnabled = value
      ribbon.InvalidateControl("btnRibbonXPS")
      ribbon.InvalidateControl("btnBackStageXPS")
      ribbon.InvalidateControl("txtXPSPath")
      ElseIf control.Id = "chkEnablePDF" Then
      m_properties.PdfEnabled = value
      ribbon.InvalidateControl("btnRibbonPDF")
      ribbon.InvalidateControl("btnBackStagePDF")
      ribbon.InvalidateControl("txtPDFPath")
      End If
      

  3. Create the method that will perform the export when the buttons are clicked
    1. Open Ribbon.vb(in case of VB) & Ribbon.cs(in case of C#) by double clicking it in the Solution Explorer
    2. Add the following using statements to the file
      C#Copy Code
      using Microsoft.Office.Interop.Word;
      
      Visual BasicCopy Code
      Imports Microsoft.Office.Interop.Word
      

    3. Create a new method named ExportDocument that will use the ExportAsFixedFormat document method to export the current document
      C#Copy Code
      public void ExportDocument(Office.IRibbonControl control)
      {
          switch (control.Id)
          {
              case "btnRibbonXPS":
              case "btnBackStageXPS":
                  Globals.ThisAddIn.Application.ActiveDocument.
                      ExportAsFixedFormat(
                          m_properties.XpsExportPath,
                          WdExportFormat.wdExportFormatXPS);
                  break;
              case "btnRibbonPDF":
              case "btnBackStagePDF":
                  Globals.ThisAddIn.Application.ActiveDocument.
                      ExportAsFixedFormat(
                          m_properties.PdfExportPath,
                          WdExportFormat.wdExportFormatPDF);
                  break;
          }
      }
      
      Visual BasicCopy Code
      Public Sub ExportDocument(ByVal control As Office.IRibbonControl)
      Select Case control.Id
      Case "btnRibbonXPS", "btnBackStageXPS"
      Globals.ThisAddIn.Application.ActiveDocument.ExportAsFixedFormat(m_properties.XpsExportPath, WdExportFormat.wdExportFormatXPS)
      Case "btnRibbonPDF", "btnBackStagePDF"
      Globals.ThisAddIn.Application.ActiveDocument.ExportAsFixedFormat(m_properties.PdfExportPath, WdExportFormat.wdExportFormatPDF)
      End Select
      End Sub
      

  4. Add the onAction attributes to all of the buttons in the Ribbon and Backstage
    1. Open Ribbon.xml by double clicking it in the Solution Explorer
    2. Add a onAction attribute to every button element
      XMLCopy Code
      <button id="btnRibbonXPS"   
        onAction="ExportDocument" 
        ... /> 
      
    3. Note:
      You should find 4 button controls

Exercise 1 Verification

In order to verify that you have correctly performed all steps in the above exercise, proceed as follows:


Test the Add-in

Test your add-in to confirm that the export ribbon and backstage buttons work as expected.

  1. Run the add-in and verify the enable checkboxes work
    1. In the Debug menu, click Start Without Debugging
    2. Once Word 2010 loads, type a phrase in the document and click the Backstage button (labeled as File)
    3. In Backstage switch to the Export tab
    4. Check the Allow XPS Export check box
    5. Enter an Export Path of C:\Office2010DeveloperTrainingKit\Labs\OfficeUI\Source\[language]\Starter\Export.xps

      Figure 4
      Export as XPS


  2. Click the To XPS button and using Windows Explorer navigate to the folder and open the Export.xps document. Close the .xps file.
  3. Verify the Home ribbon contains a new Quick Format button
    1. Switch to the Home ribbon tab and type an additional phrase into the document
    2. Click the Quick Export button and click the XPS button. Navigate to the .xps document and view it again to see your changes.

      Figure 5
      Quick Export Ribbon Button


  4. When you are done cleanup and remove the add-in
    1. Close Word 2010
    2. In the Solution Explorer, right click Word2010AddIn and click Clean