Dependency Injection with PCLs in Xamarin

A Portable Class Library (PCL) allows you to target the platforms you wish to support, and use Interfaces to provide platform-specific functionality. This is also known as dependency injection. You will often run into limitations with PCLs with UI-related needs which require specialized handling on each platform. In my example I will be using the Xamarin.Mac and .NET Framework 4.5 Frameworks. Other frameworks such as Windows 8, Xamarin.Android and Xamarin.iOS will automatically be included. This is a desktop app that runs on Windows and OSX, and shares code with a PCL.

Creating the Solution and Projects

I began by creating a new project in Visual Studio. Search for Portable. I chose Class Library (Portable) under C#. I did not choose the Class Library (Xamarin.Forms Portable) because I am not referencing that library in my non-mobile application. Name it Portable, select your frameworks and create.

Next, I renamed my solution to Proj. I just wanted to distinguish it from my different projects. All your files are stored in a root folder named Portable. This can be renamed later to match the solution name if desired. I then right-clicked on my solution to add a new project. I chose WPF Application and named it Win. I set it as my startup project. On my OSX Laptop I also opened the same solution in Xamarin Studio. It showed the Win project as unsupported and that’s fine. On the solution I went to Add New Project. Under Mac App I chose a General Empty Project. I named it Mac. Once complete set it as the Startup Project. Back in Windows I reopened my solution it gave me an Unsupported notice and migration report about the Mac project. Disregard.

PCL Code

Now let’s write some code. In my example I am going to retrieve Machine Information. In my experience I have struggled to find a PCL nuget that could fetch detailed platform machine information. Under my Portable I added a new class called IPlatform. Inside it I created an interface:
Next, I created an PlatformManager class with the following code:
Next, I added a third class to the portable. I named it StaticUtils

Windows Project Code

Now we need to create the proper hooks in our Win project. In my app.xaml.cs file I added the following:
Next, I added a class called WinInterface I added this code:

Mac Project Code

In my AppDelegate.cs file I added the following:
Next, I added a class called MacInterface I added this code:

How It All Works

The platform project starts and instantiates their class of methods implementing the portable interface. We then call an assignment method in the portable’s StaticUtils class. The assignment method instantiates a new, static PlatformManager for us to reference, and the manager stores the passed interface into a variable within itself. With a static reference we can access it through the life on the application. Now, when we want to fetch our platform method details we reference the static PlatformManager, which references the interface that implements the platform-specific code. Calling it like so will return the desired data:
Download a working example developed in Visual Studio 2013.

Read More

Customize NSComboBox Items in Xamarin.Mac

Have you ever wanted to change the color or fontweight of an item in a NSComboBox? Making an item red or bold can give attention to options you want the client to choose.

In this example I will be populating the NSComboBox I declared in Xcode via a data source. The ObjectValueForItem method is where we do our item customizations:
Lastly, assign the data source when the window loads

Read More

Balloon Tip Alternative in Xamarin.Mac

In Windows, a system tray application can popup a message for the user above the icon without interaction. This is commonly referred to as a balloon tip notification or a balloon tooltip. NSUserNotification exampleThis kind of functionality seems to be absent from Mac. Not only that, if you did accomplish something similar it would be unconventional. When making applications on different platforms you must decide what features should be identical and what should be comparable. In Mac the equivalent effect is a NSUserNotification. The messages slides out from the top-right of the screen, not from underneath an icon. This class was introduced in OSX v10.8, so if you must support older systems then look into the Growl framework.

The below example shows how it is done. The message is formed, events handlers are set and the notification is shown:
I experienced trouble at first getting this to work. But my error had nothing to do with the code. I was using VNC on my Windows machine to interact with a Mac laptop. The Mac lid was closed. It wasn’t till I opened the lid that the notifications started appearing. Notification settings can be tweaked in System Preferences under Notifications

Read More

Click Event of NSStatusItem in Xamarin.Mac

This issue annoyed me a bit so I thought I’d share. I was working with an application that had a NSStatusItem (also known as a Menu Extra). This is the Windows equivalent of a system tray application. My goal was to show the status of my application in the top item of its context menu. I had a variable in a shared project that’s updated with a status. I struggled to find a way to bind this variable to the NSMenuItem in a slick way. Then it occurred to me that I could update it as the menu opens. I needed to find an event equivalent to opening/showing/expanding. I came across an example online using the Action property of the NSStatusItem. It is more like a Click or Activated event. So that’s what I used.

For some reason I struggled to get it to fire. I eventually came across this Apple documentation. It says setting the Menu property at runtime negates the Click event. So I had to find a way to assign the menu in a different way to keep the event in tact. Whatever I found must be dynamic.

I accomplished this with the PopUpStatusItemMenu method.
Variables explained:
  • statusItemNSStatusItem
  • menuAuthStatusNSMenuItem
  • menuAuthNSMenu
  • Client.TrayStatus – the string variable in a shared project
Now each time the icon is clicked the item text of the menu is immediately set to the shared variable. Then the menu is presented to the user in all its glory!

Read More