Dynamically Changing the Visibility of Groups and Controls in the Office 2010 Backstage View
Summary: Learn to dynamically change the visibility of controls that are based on actions taken in other controls in the Office 2010 Backstage View.
Applies to: Microsoft Office 2010 | Microsoft Excel 2010
Published: May 2010
Provided by: Michael Case, iSoftStone
The Microsoft Office Backstage view, new to Office 2010, replaces the traditional File menu to provide a centralized space for file management tasks such as opening new or existing files, defining document properties, and sharing information. Like the Microsoft Office Fluent ribbon, the Backstage view is fully extensible by using XML to define the structure, components, and callback procedures to give those components functionality. In certain instances you may want to hide or display Backstage view controls based on actions the customer takes from other controls in the Backstage view. This article illustrates techniques for dynamically changing the visibility of a Backstage view group control and dynamically changing the visibility of individual controls based on customer actions. This article uses Trang Luu's Custom UI Editor to simplify adding custom user interface (UI) XML to the Microsoft Excel 2010 workbook. You must download and install the Custom UI Editor to follow the steps provided in this article.
This article customizes the Backstage view for a Microsoft Excel 2010 workbook by using a combination of XML and Microsoft Visual Basic for Applications (VBA) code. The XML defines a custom tab and the controls to display in the Backstage view. The VBA code provides the functionality required by the callback procedures defined in the custom UI XML. It also walks you through the following steps to show how to create a customized Backstage view in an Excel 2010 workbook:
Creating the Sample Excel Workbook In this Visual How To, you add custom UI XML and VBA code to an Excel 2010 workbook.
To create the workbook
Adding the Custom UI XML The Custom UI Editor simplifies adding custom UI XML to the workbook that you created in the previous step. To add the custom UI XML
Adding the VBA Callback Code The VBA callback procedures add functionality to the custom Backstage view components that you added by using custom UI XML in the previous procedure. To add the VBA callback code
View the Custom Backstage View Page To view the custom Backstage view page defined above, display the Backstage view by selecting the File tab. This is the new Backstage view. After the Backstage view is displayed, select the Dynamic Visibility tab, which is located on the built-in Info tab. When you select the Dynamic Visibility tab, the custom Backstage view page defined in the previous steps is displayed. Figure 1. Custom Backstage view page
Extending the Office 2010 Backstage view to include custom pages and controls requires a combination of adding custom UI XML to the Office document and adding VBA code to provide functionality for the callbacks specified in the custom UI XML. The sample code shows how to dynamically change the visibility of a Backstage view group control or the visibility of individual controls based on actions taken using other controls in the Backstage view. Initialize the Custom UI In some cases, a callback procedure makes a change that requires redisplaying Backstage view controls. To redisplay Backstage view controls, call the Invalidate method or the InvalidateControl method of the RibbonUI object. The following code example shows how to store a reference to the RibbonUI control when the custom UI is loaded. The customUI element contains the onLoad attribute. In this instance, the attribute specifies the OnLoad callback. The OnLoad callback stores a reference to the RibbonUI object. The RibbonUI object is used in callbacks to redisplay the Backstage view controls. The onLoad callback also initializes variables used in the code. <!-- customUI is the root tag of all Fluent UI customizations. --> <customUI xmlns="http://schemas.microsoft.com/office/2009/07/customui" onLoad="OnLoad"> 'Reference to the ribbon for refreshing the UI. Public processRibbon As IRibbonUI 'Variables that track the group that is displayed. Public engineeringGroupVisible As Boolean Public marketingGroupVisible As Boolean 'Variables that track the completed tasks. Public taskOneComplete As Boolean Public taskTwoComplete As Boolean Public taskThreeComplete As Boolean Public taskFourComplete As Boolean 'Callback for customUI.onLoad. Sub onLoad(ribbon As IRibbonUI) 'Store a reference to the ribbon for refreshing the UI. Set processRibbon = ribbon 'Initialize to display the Engineering Group first. engineeringGroupVisible = True End Sub Dynamically Change the Visibility of a Group Control Sometimes you may want to display a Backstage view group control that is based on actions taken by the user using other controls. This article discusses switching between displaying the Engineering Group group or the Marketing Group group based on the selection made in the Groups menu of the Specification Detail. The following custom UI XML examples show how to specify the callbacks to dynamically switch the display between the two groups. The Groups button specifies an onAction callback that switches between the Engineering Group controls and Marketing Group controls. The Marketing Group control and Engineering Group control specify the getVisibility callbacks. These callbacks determine whether the group should be displayed or hidden. <primaryItem> <menu id="switchMenu" label="Groups" imageMso="ControlLayoutStacked" > <menuGroup id="menuGroup"> <!-- The onAction callback switches between displaying the Marketing Group or the Engineering Group below. --> <button id="switchGroups" getLabel="GetSwitchGroupsLabel" onAction="SwitchGroups"/> </menuGroup> </menu> </primaryItem> ... <!-- The getVisible callback determines if the Marketing Group should display based on the current switchGroups button selection. --> <group id="marketingGroupDetails" label="Marketing Group" getVisible="GetMarketingGroupVisibility"> ... </group> <!-- The getVisible callback determines if the Engineering Group should display based on the current switchGroups button selection. --> <group id="engineeringGroupDetails" label="Engineering Group" getVisible="GetEngineeringGroupVisibility" > ... </group> The following code example shows how the onAction callback of the Groups menu in the Specification Detail, SwitchGroups, switches between displaying the Engineering Group control or the Marketing Group control. The SwitchGroups callback reverses the Boolean values of the engineeringGroupVisible variable and marketingGroupVisible variable that determine whether the group control should be displayed. After the variables are changed, the Invalidate method of the RibbonUI object is called to redisplay the Backstage view controls. When the Invalidate method is called, the getVisible callbacks for the Engineering Group control and Marketing Group control are re-executed causing a switch in which group displayed. 'Called when the Switch Groups button is clicked. 'The variables tracking which group is visible are swapped ' to switch the display between the two groups. Sub SwitchGroups(control As IRibbonControl) engineeringGroupVisible = Not engineeringGroupVisible marketingGroupVisible = Not engineeringGroupVisible 'The Invalidate method resets the UI causing all controls ' to redisplay and executing all relevant callbacks. processRibbon.Invalidate End Sub The following code example shows how the GetVisible callback and the GetEngineeringGroupVisibility callback of the Engineering Group control, and the getVisible callback and the GetMarketingGroupVisibilty callback of the Marketing Group control, control the display of the groups. Both callbacks work by returning the Boolean value of the variable that tracks if the group should be visible. 'Visibility for the Engineering Group control. Sub GetEngineeringGroupVisibility(control As IRibbonControl, _ ByRef returnedVal) returnedVal = engineeringGroupVisible End Sub 'Visibility for the Marketing Group control. Sub GetMarketingGroupVisibility(control As IRibbonControl, _ ByRef returnedVal) returnedVal = marketingGroupVisible End Sub Dynamically Change the Visibility of Individual Controls There may be instances where you want to display individual Backstage view controls that are based on actions taken by the user using other controls. This article displays an initial set of tasks for defining work scope. After these initial tasks are marked as complete, a second set of tasks are displayed for calculating costs. After all tasks are marked as complete, an image and label identifying that all tasks are completed are displayed. The following custom UI XML example shows how to specify the callbacks to dynamically display individual controls that are based on user actions in other controls. The getVisible callback of the Calculate Costs task of the category is specified to only display these tasks after the category control tasks of the Define Work Scope are marked as completed. The task complete image and task complete label controls set their getVisible callback to only display the controls after all tasks are completed. Each task control sets its onAction callback to mark the task as complete. <taskGroup id="bidProcessTaskGroup" label="Contract Bid Process Checklist" > <!-- The first task category always displays --> <!-- The onAction callback marks tasks as completed when the task is clicked. --> <category id="defineWorkScopeCategory" label="Define work and tasks - Complete tasks in order."> <task id="defineScope" label="Define the Scope of Work." imageMso="_1" onAction="SetTaskComplete"/> <task id="assignTasks" label="Assign the Tasks" imageMso="_2" onAction="SetTaskComplete"/> </category> <!-- The getVisible callback only displays the second task category after the tasks in the first category are complete. --> <!-- The onAction callback marks tasks as complete when the task is clicked --> <category id="calculateCostsCategory" label="Calculate costs - Complete tasks in order." getVisible="GetCalculateCostsVisibility" > <task id="calcManHours" label="Calculate Total Man-Hours" imageMso="_3" onAction="SetTaskComplete"/> <task id="calcOverheadCosts" label="Determine Overhead Costs" imageMso="_4" onAction="SetTaskComplete"/> </category> </taskGroup> <group id="tasksCompleteGroup" > <topItems> <layoutContainer id="tasksCompleteLayout" layoutChildren="horizontal" > <!-- The getVisible callback only displays this set of individual controls after all tasks are complete. --> <imageControl id="tasksCompleteImage" imageMso="AcceptInvitation" getVisible="GetTasksCompleteVisibility"/> <labelControl id="tasksCompleteLabel" label="The proposal is ready for review." getVisible="GetTasksCompleteVisibility" /> </layoutContainer> </topItems> </group> <!-- The getStyle callback and getHelperText callback dynamically set the Open Design Issues Group style and text based on if there are any open issues. --> <group id="openDesignIssuesGroup" label="Open Design Issues" getStyle="GetIssuesStyle" getHelperText="GetIssuesHelperText"> <topItems> <!-- The layoutChildren attribute lays out each set of issues controls horizontally. --> <!-- The onAction callback marks issues as resolved when the "Click to Resolve" button is clicked. --> <!-- The getVisible callback hides the issues after they are marked as resolved. --> <layoutContainer id="delayIssueContainer" layoutChildren="horizontal"> <button id="resolveDelayIssue" label="Click to Resolve" imageMso="AcceptInvitation" onAction="ResolveIssue" getVisible="getIssueVisibility" /> <labelControl id="delayIssue" label="Issue: Delay in Material Delivery" getVisible="getIssueVisibility" /> </layoutContainer> <layoutContainer id="equipmentIssueContainer" layoutChildren="horizontal"> <button id="resolveEquipmentIssue" label="Click to Resolve" imageMso="AcceptInvitation" onAction="ResolveIssue" getVisible="getIssueVisibility" /> <labelControl id="equipmentIssue" label="Issue: Equipment Down Time" getVisible="getIssueVisibility" /> </layoutContainer> <layoutContainer id="laborIssueContainer" layoutChildren="horizontal"> <button id="resolveLaborIssue" label="Click to Resolve" imageMso="AcceptInvitation" onAction="ResolveIssue" getVisible="getIssueVisibility" /> <labelControl id="laborIssue" label="Issue: Labor Dispute" getVisible="getIssueVisibility" /> </layoutContainer> </topItems> </group> The following code example shows how the getVisible callback and the GetCalculateCostsVisibility callback of the Calculate Costs task category control, control the display of the Calculate Costs category. Initially no tasks are completed and the GetCalculateCostsVisibility method returns False to hide the category control of the Calculate Costs task. When all tasks in the Define Work Scope category are completed, the GetCalculateCostsVisibility method returns True to display the Calculate Costs task category. 'Visibility for the second task category. 'The second task category does not display until tasks in the ' first task category are marked as complete. Sub GetCalculateCostsVisibility(control As IRibbonControl, _ ByRef returnedVal) If (taskOneComplete And taskTwoComplete) Then returnedVal = True Else returnedVal = False End If End Sub The following code example shows how the getVisible callback of the imageControl control and labelControl control, the GetTasksCompleteVisibility method, hides the tasks complete controls until all tasks are marked as completed. Initially no tasks are completed and the GetTasksCompleteVisibility method returns False to hide the tasks complete controls. After all tasks in both the Define Work Scope category and Calculate Costs category are marked as complete the GetTasksCompleteVisibility method returns True to display the tasks complete controls. 'Visibility for the task complete controls. 'The task complete controls do not display until all tasks ' ' are marked as complete. Sub GetTasksCompleteVisibility(control As IRibbonControl, _ ByRef returnedVal) If (taskOneComplete And taskTwoComplete _ And taskThreeComplete And taskFourComplete) Then returnedVal = True Else returnedVal = False End If End Sub The following code fragment shows how the onAction callback of the task control, SetTaskComplete, marks tasks as completed. The SetTaskComplete callback identifies which task was clicked and sets the appropriate task complete variable to True. After the task is marked as complete, the InvalidateControl method of the RibbonUI object is called to limit the redisplay and re-execution of callbacks to only those Backstage view controls affected by the change. Tasks in the Define Work Scope category can only affect the display of the Calculate Costs category control so the control identifier for the category control for the Calculate Costs control, calculateCostsCategory, is passed to the InvalidateControl method when these tasks are marked as completed. Tasks in the Calculate Costs category can only affect the display of the task complete imageControl object and labelControl object so the InvalidateControl method is called for each control when the tasks are marked as completed. 'Called when a task is clicked. 'Marks the task as complete and then calls the InvalidateControl method to ' redisplay only the controls impacted by the change in status. Sub SetTaskComplete(control As IRibbonControl) Select Case control.ID Case "defineScope" taskOneComplete = True 'Redisplay the second category control. processRibbon.InvalidateControl ("calculateCostsCategory") Case "assignTasks" taskTwoComplete = True 'Redisplay the second category control. processRibbon.InvalidateControl ("calculateCostsCategory") Case "calcManHours" taskThreeComplete = True 'Redisplay the task complete controls. processRibbon.InvalidateControl ("tasksCompleteImage") processRibbon.InvalidateControl ("tasksCompleteLabel") Case "calcOverheadCosts" taskFourComplete = True 'Redisplay the task complete controls. processRibbon.InvalidateControl ("tasksCompleteImage") processRibbon.InvalidateControl ("tasksCompleteLabel") End Select End Sub 'Called when a resolve issue button is clicked. 'Sets the button's corresponding issue as resolved. Sub ResolveIssue(control As IRibbonControl) Select Case control.ID Case "resolveDelayIssue" delayIssueResolved = True Case "resolveEquipmentIssue" equipmentIssueResolved = True Case "resolveLaborIssue" laborIssueResolved = True End Select 'Invalidate method is called to reset the UI causing all controls ' to redisplay and executing all relevant callbacks. processRibbon.Invalidate End Sub |
Video Length: 00:08:02 | Size: 10.4 MB | Type: WMV
About the Author Michael Case is a Senior Software Developer at iSoftStonewhere he works with clients creating custom software solutions. He has over 16 years of experience developing both desktop solutions and Web-based solutions using Microsoft technologies and the Microsoft .NET Framework. |
Note:

