-->![Interface Interface](/uploads/1/2/5/8/125873853/611712069.png)
When working with C# and .NET in a Xamarin.Mac application, you have access to the same User Controls that a developer working in Objective-C, Swift and Xcode does. Because Xamarin.Mac integrates directly with Xcode, you can use Xcode's Interface Builder to create and maintain your User Controls (or optionally create them directly in C# code).
While macOS provides a wealth of built-in User Controls, there might be times that you need to create a custom control to provide functionality not provided out-of-the-box or to match a custom UI theme (such as a game interface).
In this article, we'll cover the basics of creating a reusable Custom User Interface Control in a Xamarin.Mac application. It is highly suggested that you work through the Hello, Mac article first, specifically the Introduction to Xcode and Interface Builder and Outlets and Actions sections, as it covers key concepts and techniques that we'll be using in this article.
You may want to take a look at the Exposing C# classes / methods to Objective-C section of the Xamarin.Mac Internals document as well, it explains the
Register
and Export
commands used to wire-up your C# classes to Objective-C objects and UI Elements.Written completely from scratch for Mac this product uses all the features of your computer that you love, with a simple to use interface, one time setup and then the ability to just click print from your favourite app. Controls for all options including Speed, Heat and even Cutters and Peelers. Exclusive Built with our own custom print.
Introduction to Custom Controls
As stated above, there might be times when you need to create a reusable, Custom User Interface Control to provide unique functionality for your Xamarin.Mac app's UI or to create a custom UI theme (such as a game interface).
In these situations, you can easily inherit from
NSControl
and create a custom tool that can either be added to your app's UI via C# code or through Xcode's Interface Builder. By inheriting from NSControl
your custom control will automatically have all of the standard features that a built-in User Interface Control has (such as NSButton
).If your custom User Interface control just displays information (like a custom charting and graphic tool), you might want to inherit from
NSView
instead of NSControl
.No matter which base class is used, the basic steps for creating a custom control is the same.
In this article will, create a custom Flip Switch component that provides a unique User Interface Theme and an example of building a fully functional Custom User Interface Control.
Building the Custom Control
Since the custom control we are creating will be responding to user input (left mouse button clicks), we are going to inherit from
NSControl
. In this way, our custom control will automatically have all of the standard features that a built-in User Interface Control has and respond like a standard macOS control.In Visual Studio for Mac, open the Xamarin.Mac project that you want to create a Custom User Interface Control for (or create a new one). Add a new class and call it
NSFlipSwitch
:Next, edit the
NSFlipSwitch.cs
class and make it look like the following:The first thing to notice about our custom class in that we are inheriting from
NSControl
and using the Register command to expose this class to Objective-C and Xcode's Interface Builder:In the following sections, we'll take a look at the rest of the above code in detail.
Tracking the Control's State
Since our Custom Control is a switch, we need a way to track the On/Off state of the switch. We handle that with the following code in
NSFlipSwitch
:When the state of the switch changes, we need a way to updated the UI. We do that by forcing the control to redraw its UI with
NeedsDisplay = true
.If our control required more that a single On/Off state (for example a multi-state switch with 3 positions), we could have used an Enum to track the state. For our example, a simple bool will do.
We also added a helper method to swap the state of the switch between On and Off:
Later, we'll expand this helper class to inform the caller when the switches state has changed.
Drawing the Control's Interface
We are going to use Core Graphic drawing routines to draw our custom control's User Interface at runtime. Before we can do this, we need to turn on layers for our control. We do this with the following private method:
This method gets called from each of the control's constructors to ensure that the control is properly configured. For example:
Next, we need to override the
DrawRect
method and add the Core Graphic routines to draw the control:We'll be adjusting the visual representation for the control when its state changes (such as going from On to Off). Any time the state changes, we can use the
NeedsDisplay = true
command to force the control to redraw for the new state.Responding to User Input
There are two basic way that we can add user input to our custom control: Override Mouse Handling Routines or Gesture Recognizers. Which method we use, will be based on the functionality required by our control.
Important
For any custom control you create, you should use either Override MethodsorGesture Recognizers, but not both at the same time as they can conflict with each other.
Handling User Input with Override Methods
Objects that inherit from
NSControl
(or NSView
) have several override methods for handling mouse or keyboard input. For our example control, we want to flip the state of the switch between On and Off when the user clicks on the control with the left mouse button. We can add the following override methods to the NSFlipSwitch
class to handle this:In the above code, we call the
FlipSwitchState
method (defined above) to flip the On/Off state of the switch in the MouseDown
method. This will also force the control to be redrawn to reflect the current state.Handling User Input with Gesture Recognizers
Optionally, you can use Gesture Recognizers to handle the user interacting with the control. Remove the overrides added above, edit the
Initialize
method and make it look like the following:Here, we are creating a new
NSClickGestureRecognizer
and calling our FlipSwitchState
method to change the switch's state when the user clicks on it with the left mouse button. The AddGestureRecognizer (click)
method adds the Gesture Recognizer to the control.Again, which method we use depends on what we are trying to accomplish with our custom control. If we need low level access the to user interaction, use the Override Methods. If we need predefined functionality, such as mouse clicks, use Gesture Recognizers.
Responding to State Change Events
When the user changes the state of our custom control, we need a way to respond to the state change in code (such as doing something when clicks on a custom button).
To provide this functionality, edit the
NSFlipSwitch
class and add the following code:Next, edit the
FlipSwitchState
method and make it look like the following:First, we provide a
ValueChanged
event that we can add a handler to in C# code so that we can perform an action when the user changes the state of the switch.Second, because our custom control inherits from
NSControl
, it automatically has an Action that can be assigned in Xcode's Interface Builder. To call this Action when the state changes, we use the following code:First, we check to see if an Action has been assigned to the control. Next, we call the Action if it has been defined.
Using the Custom Control
With our custom control fully defined, we can either add it to our Xamarin.Mac app's UI using C# code or in Xcode's Interface Builder.
To add the control using Interface Builder, first do a clean build of the Xamarin.Mac project, then double-click the
Main.storyboard
file to open it in Interface Builder for edit:Next, drag a
Custom View
into the User Interface design:With the Custom View still selected, switch to the Identity Inspector and change the view's Class to
NSFlipSwitch
:Switch to the Assistant Editor and create an Outlet for the custom control (making sure to bind it in the
ViewController.h
file and not the .m
file):Save your changes, return to Visual Studio for Mac and allow the changes to sync. Edit the
ViewController.cs
file and make the ViewDidLoad
method look like the following:Here, we respond to the
ValueChanged
event we defined above on the NSFlipSwitch
class and write out the current Value when the user clicks on the control.Optionally, we could return to Interface Builder and define an Action on the control:
Again, edit the
ViewController.cs
file and add the following method:Important
You should use either the Event or define an Action in Interface Builder, but you should not use both methods at the same time or they can conflict with each other.
Summary
This article has taken a detailed look at creating a reusable Custom User Interface Control in a Xamarin.Mac application. We saw how to draw the custom controls UI, the two main ways to respond to mouse and user input and how to expose the new control to Actions in Xcode's Interface Builder.
Related Links
Ribbon Examples files and Tips
Important : Follow the steps on the page first before you start with the examples and tips on this page : Change the Ribbon in Excel 2007 and up
Also check out the idex page for Ribbon and QAT stuff : http://www.rondebruin.nl/win/section2.htm
Note: If you are a Excel 2016 for Mac user start here : Change the Ribbon in Mac Excel 2016 and up
Download RibbonX examples workbooks
You can download 8 Excel files here with basic RibbonX examples for Excel 2007 and up
Download Example Excel files Last Updated : 10-Jan-2017
1: Add custom group in built-in tab.xlsm
2: Custom tab for Favorite Groups and buttons.xlsm
3: Custom tab for your favorite macros part 1.xlsm
4: Custom tab for your favorite macros part 2.xlsm
5: Dictator(1).xlsm
6: Dictator(2) With_Custom_Tab.xlsm
7: Disable-Visible-Repurposing.xlsm
8: Office Button or Backstage.
Download Example Excel files Last Updated : 10-Jan-2017
1: Add custom group in built-in tab.xlsm
2: Custom tab for Favorite Groups and buttons.xlsm
3: Custom tab for your favorite macros part 1.xlsm
4: Custom tab for your favorite macros part 2.xlsm
5: Dictator(1).xlsm
6: Dictator(2) With_Custom_Tab.xlsm
7: Disable-Visible-Repurposing.xlsm
8: Office Button or Backstage.
![Interface Interface](/uploads/1/2/5/8/125873853/611712069.png)
When you create your menus with Application.CommandBars in Excel 97-2003 you have code to create the menu and delete the menu. In Excel 2007 and up when you use RibbonX to customize the Ribbon this is different, when you close or deactivate the workbook it will automatic remove your customizations.
The files in the download are working OK in Excel 2007 and up.
If you want to load different RibbonX for Excel 2007 and Excel 2010 and up see :Load different RibbonX when opening file in Excel 2007 or 2010 and up
The files in the download are working OK in Excel 2007 and up.
If you want to load different RibbonX for Excel 2007 and Excel 2010 and up see :Load different RibbonX when opening file in Excel 2007 or 2010 and up
Note: For example files for changing Backstage(File) visit my Backstage page
Find the Control, Group and Tab names
You see in the RibbonX that I use for example idMso='VisualBasic' to point to a built-in control.But how do you find the names of the controls ?
Download this file from the Microsoft site: Office 2007: Lists of Control IDs
Download this file from the Microsoft site: Office 2010: Office Fluent User Interface Control Identifiers
Download this file from the Microsoft site: Office 2013: Office Fluent User Interface Control Identifiers
I create my own versions of the files for Excel above to make it easier.
Note: If you disable macros you can't use the files.
Note: If you disable macros you can't use the files.
When I have time i create a version for Excel 2013
Download example files with every idMso in the Excel 2016 Ribbon (9-Jan-2017)
Tip: ContextMenu Add-in created for Office 2010 (seems to work OK in 2013 and 2016)
ContextMenus Add-In for Office 2010 : This Com add-in from Microsoft add the idMso name of the ContextMenu on the bottom of every Context menu(Right click menu's). This is a very easy way for developers to find the idMso of the menu so they can use it in the RibbonX. Note: Only In 2010-2016 you can change the ContextMenu's with RibbonX. The add-in also seems to work OK in 2013 and 2016. Download Microsoft ContextMenusaddin
See this example page : Customizing Context Menus in Microsoft Excel
Find the names of the button images
You can see in the RibbonX that I use imageMso='HappyFace' to use the built-in image I want. But how do you find the names of all the images?
Download this file from the Microsoft site Office 2007 : Icons Gallery
Download this file from the Microsoft site Office 2010 : Icons Gallery
As far as I know there is no Icons Gallery for Office 2013 and 2016.
Or try this two add-ins from Ken Puls and Jim Rech
Identifying your imageMso – Excel, Word & Powerpoint Add-in from Ken Puls, It’s labelled as 2007, but still works in 2010-2016, maybe it is safer to use the 2007 images so its backwards compatible.
Control Image Add-in for Excel 2007 and Excel 2010 but also working in 2013 and 2016 (made by Jim Rech). Jim's add-in displays the images on buttons in the Ribbon (by adding a new tab), he has tried to remove most or all duplicate images and, in the case of Excel 2007, added a few images not in the MS list.
Download it from my site : File date (18-Nov-2015)
Download it from my site : File date (18-Nov-2015)
Edit the Ribbon with a Add-in
Try this Add-in : RibbonX Visual Designer Add-in (made by Andy Pope)
http://www.andypope.info/vba/ribboneditor.htm
http://www.andypope.info/vba/ribboneditor.htm
Hide/Show the Ribbon/QAT with VBA
You can use this VBA example posted by Jim Rech to Hide/Show the whole Ribbon and the QAT.
Only in Excel 2010-2016 you can use this to hide the view of only the Ribbon
CommandBars.ExecuteMso 'MinimizeRibbon'
You can use a function to check the state of the Ribbon in 2007-2016
CommandBars.ExecuteMso 'MinimizeRibbon'
You can use a function to check the state of the Ribbon in 2007-2016
Hide the MRU('Most Recently Used') file list
Note: In Excel 2010-2016 it is no problem anymore to hide the MRU list, see my backstage page.
There is no built-in option to disable the MRU('Most Recently Used') file list in the Office button menu in 2007. Try this example file that create a new tab on the Ribbon and hide/disable a few controls with RibbonX and with VBA code from Jim Rech disable the MRU list.
Part from the comments in the code from Jim:
Because there is apparently no way to disable the MRU list on the Office Menu directly we clear it by setting Application.RecentFiles.Maximum to 0. Since this action clears the MRU list in the registry we first backup its contents to the registry as well as number of files the user is showing in it. We use the registry in case VB variables are cleared.
Download the example file
There is no built-in option to disable the MRU('Most Recently Used') file list in the Office button menu in 2007. Try this example file that create a new tab on the Ribbon and hide/disable a few controls with RibbonX and with VBA code from Jim Rech disable the MRU list.
Part from the comments in the code from Jim:
Because there is apparently no way to disable the MRU list on the Office Menu directly we clear it by setting Application.RecentFiles.Maximum to 0. Since this action clears the MRU list in the registry we first backup its contents to the registry as well as number of files the user is showing in it. We use the registry in case VB variables are cleared.
Download the example file
Examples for a dropdown in the Ribbon
You can download a zip file with two basic examples below.