Improving CF App Aesthetics

One complaint I see a lot about apps built using the Compact Framework is that they look terrible.  It doesn’t have to be that way, and honestly the Compact Framework really isn’t at fault here.  Generally speaking the problem is that developers are lazy and want to just use what’s in the off-the-shelf toolbox.  If you do that, then yes, you’ll have something that looks like a Windows 95 application.  But again, I don’t fault the CF for that, I fault developers (or more likely their managers).

If you want an app to have good aesthetics you need two things:

  1. To hire a real graphic designer to at least produce collaterals
    At the risk of making broad generalizations, I’ll state that developers suck at producing graphics (it’s OK, graphic designers suck at writing code).  You wouldn’t hire a plumber to hang drywall, why on earth are you having developers create UI?  Hire a designer that has experience building UI collaterals and you’ll find that not only will your app look a thousand times better, it will get done faster than having your devs hack at it.
  2. To break your developer’s reliance on the off-the-shelf controls
    Using the controls that install with the CF is a sure-fire way to end up with a dated-looking app.  This doesn’t mean you have to go buy a 3rd-party set of controls; that may help, but don’t just assume it’s going to solve the issue.  What we’ve done internally is to build a set of controls that we use.  Most people would be surprised to know that we have a very small set. We wrote the entire device application for a commercially-available time clock that you’d never know was based on CE by looking at it and I believe that the number of Control types used (other than a Form and SmartPart) was one.  That’s right – we used a single control type for everything.  We use it as a Button, a Label, a CheckBox and stacked together to make a List (it’s a touch device with only 5 or 6 items visible at a time).

There’s not much I can do for you on point #1, but for #2 I can at least give you the control we use.  It’s called ImageButton due to it’s genesis as a button that, surprisingly, held an image.  It got more complex as we needed and added new capabilities and features.  You can set the up and down images (to get that nice “inverted” look on click), put align text left, center or right (with an appropriate margin if you’d like), put text and images together, and several other features.

Here are some quick screen shots:

The first screen shows rounded buttons (the change to a blue background when clicked) with the grey “>” and the text aligned in different ways.  Note that the right and left justified text have a fairly large margin; this is settable.

The second is probably not the greatest picture as it looks a lot like a normal checkbox, but those checkboxes are actually images.  You could easily change them to a round “bubble” or a box with a check that extends beyond the box border.

The third is a simple drawn-gradient background.  Note that the button in the upper middle (which again is an ImageButton) has rounded corners and the gradient background is visible through the transparent corners of the button (this was a real challenge in the CF).  The “State1” text on this view is actually another ImageButton control so it can respond to clicks.  Again note that the gradient background is visible through the control.

The final view shows yet another use of the control.  The two-state capability is actually done with two images. The control is a single ImageButton and when it gets clicked, we swap the image to toggle the “on” or “off” selection. Notice that the text in the images is less pixelated becasue we don’t have ClearType turned on.

Since I didn’t really have a better place to put the code, and since the sample app showing it was using the IoC framework, I’ve simply put the code in the OpenNETCF IoC Framework tree on Codeplex (under Samples). Also note that the code for this is not yet in the release. That means you need to pull it from the source view (starting with change set 59250)

Updates to ORM and IoC projects

We’ve shipped a first version of a customer project.  That’s always good news, but the benefit to the community at large is that updates, improvements and fixes to both the ORM and IoC projects from that project have now propagated to the public code bases.

The IoC changes are pretty minor, which tells me that it’s a pretty robust and mature library on the whole.

ORM had a load of changes in the SQL Compact implementation.  The interface for the DataStore has expanded by several methods due to use-cases I needed methods for and it’s got a whole lot of performance improvements added.  ORM and is now shipping to real-world customers in a handheld product, so I consider it “release” quality.

Be aware that neither project has these changes rolled into a release package yet, so if you want these changes, grab the latest change set from the “Source Code” tab on the appropriate project page.

OpenNETCF IoC: Now supporting WinPhone!

Today I decided to finally get around to testing out the IoC core library on Windows Phone 7.  Of course I couldn’t be lucky enough for it to just compile out of the box and work. The usage of the Control class for marshaling events made it a little bit challenging, but it really didn’t require a whole lot of code changes to get the code base to continue to work for the Desktop, the Compact Framework and Windows Phone.  The latest release now has a solution and a Silverlight project for WinPhone.

Why would you want to use this IoC container?  Well I use it becasue it’s lightweight and because I can use the same framework everywhere.  I don’t have to learn a new framework when I’m using the desktop, the CF and now the phone.  It keeps my life simpler and allows better code reuse for me.

OpenNETCF.IoC : Location Module

Since I use the OpenNETCF.IoC framework in just about every project I do any more, you can imagine I’ve created a pretty good collection of Modules and Services for common business problems I run into.  I’ve decided that I’m going to start putting some of these out in the public domain along with the framework and my first release is the OpenNETCF.Location module.  It’s basically a module that prvides a GPS location service (GpsService to be exact). 

The default implementation is wrapper around the GPS intermediate driver, but it’s not using the CF classes that Microsoft ships with the WinMo SDKs.  I looked at Microsoft’s implementation and it felt really ugly to me, so I rewrote it the way it should have been done in the first place.  I don’t yet have a simple sample application extracted for it (I have apps that use it, but they’re too complex for a sample), but I’ll add one as time permits.

The code is part of the latest change set (49823) – it’s not yet in the release download – so if you want it, get it off of the Source Code page.

Connecting to TFS 2010 from Studio 2008

Codeplex recently updated the server hosting the IoC project to TFS10.  Since we still have to use Studio 2008 for device development, I had to do some client changes for bindings to get to the server.  TFS 2010 added the concept of a “Team Project Collection”, which Codeplex is using – but Studio 2008’s Team Explorer dialog has no provision for it.  It took me a while with a search engine to figure out how to actually attach – basically you have to manually type the full path into the connection dialog in Team Explorer like so:


So for the new TFS10 on Codeplex, it looks like this:

IoC: Registering Concrete Types for Interfaces

One drawback to the OpenNETCF.IoC framework was the difficulty in making object generation loosely coupled.  This is especially true when object types you want to create change depending on your runtime environment.  For example let’s say we have an interface IAccelerometerService.  Different devices have different implementations, and the emulator and your integration tests don’t even have hardware so they need a simulator.  So you create some classes that derive from the interface like this:

public interface IAccelerometerService

public class DeviceAAccelerometer : IAccelerometerService
// handles the accelerometer by using APIs for device A

public class DeviceBAccelerometer : IAccelerometerService
// handles the accelerometer by using APIs for device B

public class SimulatedAccelerometer : IAccelerometerService
// simulates an accelerometer (emulator, test use, etc)

That’s all well and good, but let’s say we have a generic infrastructure module that does the object creation and injection.  We don’t want it to have to know about the concrete class types. They might be in separate assemblies that may not even exist – you certainly don’t need (or want) to ship emulator implementation for your hardware. 

How would you handle this? The IoC framework doesn’t like the following construct:


Because it has no idea what concrete type you want it to create.  In this case it will throw an IOCException.

Today I added a “registration” process to the framework.  You now can do the following:

RootWorkItem.RegisterType(typeof(SimulatedAccelerometer), typeof(IAccelerometerService));

This tells the RootWorkItem that when you call to create an item of type IAccelerometerService, it should actually create an object of type SimulatedAccelerometer.

Each ManagedObjectCollection (so Items, WorkItems, SmartParts and Workspaceas) keeps track of its own Dictionary of type mappings and calling RegisterType on a given WorkItem calls the registration for each.  You can explicitly call RegisterType on any one of the collections directly and “override” an existing registration.  This means that you could have Items create one type and SmartParts create another type for the same interface.  I’m not sure when you’d ever want to do that, but I’ve provided for it.

Hopefully this makes the IoC framework a little more friendly, especially for testing (which is already painful enough for devices), and helps you, as a developer, develop your solutions faster without having to think about the underlying framework.

Connecting to Codeplex from Studio 2008

Codeplex is in the process of upgrading their servers to TFS2010.  It isn’t very clear, however, how to attach to the upgraded servers from older versions of Studio (like Studio 2008, which is required for all device development).  The answer is that you have to install a “forward compatibility update“.