Nick's .NET Travels

Continually looking for the yellow brick road so I can catch me a wizard....

User Interface Guidelines for Mobile Devices

One of the areas that I revisit from time to time is how user interfaces are designed for mobile devices.  Despite being crucial to user adoption most developers don't worry too much about the interface design for desktop applications.  Luckily due to monitor/screen sizes going up this is less of an issue as we can usually work out the mess and still be productive.  Unfortunately on a mobile application if you don't get the user interface right (or at least make an effort to think about how a user might use your application) your application will not be used (full stop!). 

So, lets start with the basics - these are guidelines for usability not necessarily guidelines for good user interface design:

Watch out for low flying objects.....

Ok, the title was just to get your attention but hey this is pretty important news, so worth making the effort.  I've just found out that the date and city have been announced for the Microsoft Mobile and Embedded DevCon 2007, here in Australia.  That's right on May 16th in Sydney we are going to get the best of the international presentations from MEDC Las Vegas here downunder!  This information was recently published on the homepage of the international MEDC homepage (www.medc2007.com), although you have to click the "Register" button for the dates/locations information or you can just follow this link for the full list.

Look forward to seeing as many people as possible in Sydney this year!

Raising Custom Events

Earlier today I was wading through the code for the Microsoft Sync Services (many thanks to Lutz Roeder's Reflector and the file disassembler addin) so that I could understand how it all pieces together.  One of the interesting things I noticed was that in a couple of places they had appeared to write their own custom events which look a bit like:

public event EventHandler<ApplyChangeFailedEventArgs> ApplyChangeFailed
{
      add
      {
            this.Events.AddHandler(DbServerSyncProvider.EventApplyChangeFailed, value);
      }
      remove
      {
            this.Events.RemoveHandler(DbServerSyncProvider.EventApplyChangeFailed, value);
      }
}

 
Later in the code they then raise this event with the following untidy bit of code:

protected virtual void OnApplyChangeFailed(ApplyChangeFailedEventArgs value)
{
      EventHandler<ApplyChangeFailedEventArgs> handler1 = (EventHandler<ApplyChangeFailedEventArgs>) this.Events[DbServerSyncProvider.EventApplyChangeFailed];
      if (handler1 != null)
      {
            handler1(this, value);
      }
}

This got me thinking about how this would be written in VB - thanks again to reflector I ended up with

        Public Custom Event ApplyChangeFailed As EventHandler(Of ApplyChangeFailedEventArgs)
            AddHandler(ByVal value As EventHandler(Of ApplyChangeFailedEventArgs))
                Me.Events.AddHandler(EventApplyChangeFailed, value)
            End AddHandler
            RemoveHandler(ByVal value As EventHandler(Of ApplyChangeFailedEventArgs))
                Me.Events.RemoveHandler(EventApplyChangeFailed, value)
            End RemoveHandler
            RaiseEvent(ByVal sender As Object, ByVal e As ApplyChangeFailedEventArgs)
                Dim handler1 As EventHandler(Of ApplyChangeFailedEventArgs) = TryCast(Me.Events.Item(EventApplyChangeFailed), EventHandler(Of ApplyChangeFailedEventArgs))
                If (Not handler1 Is Nothing) Then
                    handler1.Invoke(sender, e)
                End If
            End RaiseEvent
        End Event

Ok, so that's the event declaration - you will notice that most of the code to do with raising the event has now been moved into the RaiseEvent part of the custom event.  Now when we raise the event we just do:

        Protected Overridable Sub OnApplyChangeFailed(ByVal value As ApplyChangeFailedEventArgs)
            RaiseEvent ApplyChangeFailed(Me, value)
        End Sub

I think you would agree this is much tidier from a consumer point of view!

SQL Server Compact Edition - Community Portal

Over the last couple of weeks I've been slowly putting together a new community portal to focus on what I think is a very relevant technology that will impact the way we build applications.  SQL Server Compact Edition and accompanying technologies such as the Microsoft Sync Services (currently in CTP) will form the basis for new productivity applications. 

To this end I would like to introduce www.sqlserverce.org, which can also be found at any of the following urls:

 

Keyboard shortcuts in Visual Studio 2005

I was just reading Jason McC's Weblog and he points out that the are some great wallcharts available for download that cover a large proportion of the keyboard shortcuts for different profiles (you can get the list of downloads here).  Unfortunately even in a book dedicated to Visual Studio 2005 such as "Professional Visual Studio 2005" there isn't really enough space to go into all of the shortcuts.  This is especially true when the shortcuts are configurable both in the initial profile you select and then via the Tools->Options dialog. 

Missing:  What's missing is of course the "General" profile - for the most part AFAIK these are basically the same as the C# profile settings w.r.t the keyboard.  IMHO there should be a VB6 profile (which would be the settings currently in the VB profile) and a VB.NET profile (which would be the shortcuts etc that all  developers coming from VS2003 would be used to).  Despite being a VB.NET advocate I wouldn't touch the VB profile with a 30ft barge pole as it is just plain confusing for anyone who has worked with VS (since .NET started).

Windows Mobile 6

So I'm not the first, and won't be the last, to blog about this but I just thought I'd add the appropriate links:  Windows Mobile 6 has been announced which of course will come with a whole set of new features. In case you were wondering here are a couple of people from within Microsoft who have more on what you will expect to see: Jason and Loke

Anyone for some Blogarate?

As a number of you will be aware Clarke has been doing some awesome work in the community/blog space.  The first of these is of course whooiz - if you don't already have an online profile here I highly recommend getting one - which has plugins for a number of blog engines such as Community Server.  This enables you to not only reuse information from whooiz for your About page (see mine here) it also allows you to list friends, blogs you read etc.

The next feature that Clarke has been working on is the ability to rate a blog just by giving it a star rating - if you look closely at my blog you will see the rating bar at the bottom (currently with a "powered by Blogarate" sign under it).  Blogarate, according to Clarke's post, is currently in private beta and we are already starting to see a collection of blog posts being rated.  Update your blog engine according to these instructions to start receive your ratings.

Doing the &quot;right&quot; thing

I was suitably impressed that Dan provided feedback to my previous post re the patent around the Object Test Bench v's BlueJ issue in which he covers the two points I was trying to make:

  1. The patent shouldn't have happened - congrats to the team for admitting that they are only human and that mistakes do happen.  Along with the BlueJ community (which I don't actually belong as I think this is flogging a dead horse) I'm interested to see the answer to "why did this happen in the first place".  I think they would also like to see some attribution of the work that was done in this area prior to VS2005.
  2. The second point was that OTB has limited use - why do I say this and what features would I ask for? I appreciate that Microsoft is always listening to the community (for which I'm very impressed) but these two bits of feedback were either ignored or sidelined as not important:
  • OTB only works with the project that is marked as startup - and this includes class libraries.  If you are working on a class library (as part of an application) and you want to try something with a class you have to set that project to be the startup, experiment with the class, then set the application back to being the startup project
  • OTB has no memory - you can establish quite complex object graphs only to have them blown away when you rebuild/make changes to your application.

I'm sure there are other bits of feedback that I would provide on the OTB but these are the two sore points from my point of view.  Thanks again Dan for opening the discussion on the future of the OTB

Getting OneCare an WMDC to play together

Late last year I posted about my frustration with the betas of OneCare and the Windows Mobile Device Center (WMDC) not playing well together on Vista.  Now that both have been released I'm pleased to pass on the fact that there is a work around to get the two products to play together properly (many thanks to the guys at MoDaCo who posted this).  Of course this doesn't help if you are experiencing the same issues as Mauricio!

Bogus Patent for what?

I was just doing a bit of catchup reading and noticed a post on Dan Fernandez's blog about a recently withdrawn patent that was for the Object Test Bench (OTB) that was introduced into Visual Studio 2005.  Having had a bit of experience with BlueJ while tutoring at UWA I was very disappointed in the limited functionality in the OTB.  In fact I would go so far as to claim that it was useless for anything but simple demonstrative examples - definitely not the production IDE quality that I would have expected (the same I must admit is true of the Class Designer). 

With this in mind I was shocked to learn of the patent that they apparently "accidentally" (what rubbish) submitted.  Following the link on Dan's blog I read the post that Michael makes and his original comparison he did between the OTB and BlueJ.  Seriously, if you are going to patent something (which clearly wasn't original) you could at least make it usable!

Microsoft Sync Services Configuration Example

Over the last couple of days I have been putting together some sample code that will significantly reduce the amount of code you have to write to work with the Microsoft Sync Services.  Unfortunately one of the major issues with MSS is that you are responsible for nearly everything (unlike Merge which is pretty simple once you have set up the publication).  The configuration sample which can be downloaded here moves all the tedious code out to a configuration file, freeing your application up to delievery functionality!!!  This sample reworks the original samples from the Synchronizer blog, Demo I, II and III

Oh, and if you hadn't guessed there is a reason why I recently blogged about .NET v2 Custom Configuration Sections.  <Shameless plug>If you are interested in learning more about these then you should purchase a copy of Professional Visual Studio 2005 which covers this in detail, including how to get intellisense within Visual Studio 2005 for your custom configuration sections.</Shameless plug>

User Interface - Who thinks it's important?

I've just finished listening to two of Ron Jacob's Arcast shows both of which covered aspects of User Interface. With the work that we are doing at Intilecta this is clearly an area that we place a strong emphasis on as part of our product development process.  What I don't get is why everyone has suddenly decided to focus so heavily on user interface.  Perhaps it is the fact that Microsoft (and most other technology companies) was whipped by Apple when they stormed the market with the iPod.  With the recently introduced Zune it is clear that Microsoft is trying to put a stop to this market dominance but will they be in time to stop the iPhone???

If you look at the recent product releases and announcements from Microsoft it is clear that there is a significant move to combat this "lack of user interface".  Just to name a few: WPF, Expression Suite, Vista, Office 2007, WPF/e, Atlas and the list goes on.  In fact if you look at the structure of Frank's new look team you can see that user interface has it's own evangelist. 

Ok, quick question to the floor - who has been involved in a project (that is going to have some sort of user interface) where they haven't said "we want a user interface that really engages the user"?  I think that there has been enough talk about user interface so it is at least a consideration when we build an application.  Further there needs to be a distinction between poor user interface and stupid users.  One of the snippets on one of the podcasts was that the automated checkin stations at airports were poorly designed because a particular passenger didn't read the screen and was left waiting for his ticket (the part he didn't read was that because he was in an exit row he had to pick up his ticket from the counter).  Hey you can take a horse to water but you can't make it drink - there is no excuse for user being idiots!!

Looking at two of the technologies in the list above, here are some comments:

Ajax/Atlas - One of the issues I have with this technology is that it is a patch for a generally faulty technology.  The whole concept of web applications with a request-response model has a fundamental latency that can only be minimised or hidden.  If this is done well (which can be done with Ajax/Atlas) then you have a web site that is pleasant to use but still no comparison to a rich user experience that could be achieved with a full client application.  I think the next step in this direction will have the returns that the web world are really chasing - WPF/e will provide a cross-platform, server deployed solution that has a rich user experience including media content.

WPF - Ok this is a technology that absolutely rocks.  If you know what you are doing you can build a rockin application that is a real joy to use (I must confess I haven't seen such an application yet but I've been sold on the bouncing/rotating buttons!).  The issue I see here is that Microsoft are trying to get developers to use another technology because it "might" improve their user interface.  Most of the issues I actually see with most user interfaces is that developers don't understand how to do proper user interface/framework separation - by this I mean the ability to carry out long running actions on a background thread so that the application remains responsive at ALL times.  This issue isn't fixed by WPF and will continue to be an issue long into the future.

One point I would like to make in closing is that Ron chats with Simon Guest who has a great (although relatively simple) framework for building good user interfaces.  He separates user interface design into three parts:

Visualisation - How information is presented.  Intilecta provides this in the form of content panels and a navigation tree that is easy to navigate and intuitive.  We reuse knowledge established within the team to build a user interface that optimises the presentation of data so the user can see the information they need.

Foundation - Which patterns the application is going to use in order to reduce the amount of code a developer has to write again and again (and again).  IMHO if you have to write it twice you have written it once too many!  We had to build our own user interface framework as we found the Composite UI block to be too complex for what we wanted to do, and not a particularly good fit for the type of user interface we were building.

Context - This is how your application integrates into the total user experience.  In our case we have identified that Outlook is one of the primary business tools that our clients use.  As such we have ensured that whatever we do will integrate seamlessly into Outlook so that the user doesn't waste time context switching.

In closing I would like to reiterate the importance of user interface.  Don't take my negative comments as a reason not to get into these technologies and start building better applications.

.NET v2 Configuration Sections

Anyone who has written a custom configuration section handler for .NET v1 will appreciate the headaches and the painful process of parsing an xml block.  Well .NET v2 has a much better model for building custom configuration sections.  In this post I will walk you through the basics:

Getting Started: You need to make sure that your application has a reference to System.Configuration.  While by default there is a System.Configuration namespace it is quite limited and doesn't include the classes you need to build your own custom sections.

We will start with a simple scenario and build it up.  In this case the scenario is that you want to store information about a Person in the configuration file.  Initially you only need to track a single person and you are only really interested in their name.  The easiest way to do this would of course just to add an entry to the appSettings section of the configuration file (alternatively you could use the Application Settings area using the UI designer in Visual Studio 2005 - but we will leave this discussion for another time when we look at application settings):

<appSettings>
   <
add key="Person" value="Fred"/>
</
appSettings>

While this serves the purpose it might mean that this setting gets mixed up with the other settings you might have defined for your application.  It also means that in code you have to do a by-name lookup for that value:

MsgBox(ConfigurationManager.AppSettings("Person"))

This is where we can define our custom configuration section.  The first thing you need to do is define what the custom section is going to be called and the name of the .NET type that is going to be used to access the section information.  This is done with an entry into the configSections area of the configuration file:

<configSections>
   <
section name="CustomConfig" type="ConfigurationSample.MySection,ConfigurationSample"/>
</
configSections>

In this case the name of the configuration section in the configuration file will be CustomConfig and this will be loaded using the class MySection in the ConfigurationSample namespace.  This class is located in the ConfigurationSample assembly.  The next thing to do is to create the custom section in the configuration file.  Initially the entry will just be an entry section:

<CustomConfig/>

Now that we have set up the configuration file we need to create the MySection class that will be used to load this information at runtime.  Again initially this class will be very basic as there is no information to load:

Public Class MySection
   Inherits ConfigurationSection
End Class

To access this section in code you simply use the ConfigurationManager (as will the appSettings information) but this time you use the GetSection method to retrieve the MySection object:

Dim sect As MySection = TryCast(System.Configuration.ConfigurationManager.GetSection("CustomConfig"), MySection)

Now that we have the basics it is time to go back and gradually add information to the custom section.  We will start with including a Name attribute in the section itself:

<CustomConfig Name="Fred" />

In the MySection class you simply define a property through which you can access this information:

Public Class MySection
  
Inherits ConfigurationSection
   <ConfigurationProperty("Name", IsRequired:=True)> _
  
Public Property Name() As String
     
Get
        
Return TryCast(Me("Name"), String)
     
End Get
     
Set(ByVal value As String)
        
Me("Name") = value
     
End Set
  
End Property
End Class

Accessing this in code is as simple as making a call to the Name property of the MySection object:

Dim sect As MySection = TryCast(System.Configuration.ConfigurationManager.GetSection("CustomConfig"), MySection)
MsgBox(sect.Name)

Clearly this doesn't read particularly well as it isn't really the Name of the section you are after.  What would be good is to be able to access sect.Person.Name.  This can be done using a class that inherits from ConfigurationElement.  The configuration file would be:

<CustomConfig>
   <
Person Name="Fred"/>
</CustomConfig>

And the MySection class now looks like:

Public Class MySection
  
Inherits ConfigurationSection
  
<ConfigurationProperty("Person")> _
  
Public Property Person() As Person
     
Get
        
Return TryCast(Me("Person"), Person)
     
End Get
     
Set(ByVal value As Person)
        
Me("Person") = value
     
End Set
  
End Property
End Class

Public Class Person
  
Inherits ConfigurationElement
   <ConfigurationProperty("Name", IsRequired:=True)> _
  
Public Property Name() As String
     
Get
        
Return TryCast(Me("Name"), String)
     
End Get
     
Set(ByVal value As String)
        
Me("Name") = value
     
End Set
  
End Property
End Class

And of course the code to access this information is now:

Dim sect As MySection = TryCast(System.Configuration.ConfigurationManager.GetSection("CustomConfig"), MySection)
MsgBox(sect.Person.Name)
 

But what happens if we want to store multiple people in this section.  Well there is a built in solution - all we need to do is inherit from the ConfigurationElementCollection.  This would give us a configuration section as follows:

<CustomConfig>
  
<People>
      <
add Name="Joe"/>
   </
People>
</
CustomConfig>

And the MySection now looks like (I haven't included the Person class again as it is the same as before):

Public Class MySection
  
Inherits ConfigurationSection
  
<ConfigurationProperty("People")> _
  
Public ReadOnly Property People() As PersonCollection
     
Get
        
Return TryCast(Me("People"), PersonCollection)
     
End Get
   End Property
End Class

Public Class PersonCollection
  
Inherits ConfigurationElementCollection
   Protected Overloads Overrides Function CreateNewElement() As ConfigurationElement
      Return New Person
   End Function
   Protected Overrides Function GetElementKey(ByVal element As ConfigurationElement) As Object 
      Return TryCast(element, Person).Name
   End Function
End
Class

Now the access code would be:

Dim sect As MySection = TryCast(System.Configuration.ConfigurationManager.GetSection("CustomConfig"), MySection)
For Each p As Person In sect.People
   MsgBox(p.Name)

Next

I hope that gives you an overview of how you can build your own custom configuration sections.  Of course your custom section is likely to be much more complex and make further use of the built in configuration support.  If you are interested in using this on the mobile device you will have to look to the Mobile Client Software Factory for a configuration implementation as the .NET Compact Framework doesn't have configuration support.

If you want more information on building custom sections, take a look at Professional Visual Studio 2005

Messed up Shortcuts under Vista

There are a couple of things that still puzzle me about Vista.  One of which continually frustrates me whenever I go to save something.  Instinctively I navigate to Documents (easily done via the Documents button in the left pane of the explorer window) then click on the My Pictures shortcut only to get a dialog popup and state:

[Window Title] - Location is not available
[Content]- C:\Users\nrandolph\Documents\My Pictures is not accessible. Access is denied.
[OK
]

Now I understand that they have re-routed a few of the old style folders (eg from "Documents and Settings" to "Users") but how is the average user supposed to deal with that dialog!!!

Working with the Common Feeds with RikReader

Earlier this month Doug posted version 1.3 of RikReader a free WPF (.NET v3) application that hooks into the common feeds store (the same feed store IE7 uses).  I've been playing with the earlier versions of RikReader but was disappointed as it didn't offer much over the IE7 view.  However the latest version is significantly better.  Similar to the New York Times reader there is a newspaper mode and unlike IE7 the tree on the left indicates how many unread items each node has. 

This said, here are some suggestions for improvements:

  • I like the way that IE7 highlights feeds that are unread in bold.  While I like the RikReader's indication of the number of unread messages it is located at the end of the blog name.  In the usual position the splitter bar tends to hide this on most of my feeds.  Perhaps this number could go at the beginning of the feed instead of the end.
  • I like the newspaper mode that RikReader supports, except the articles are missing the date?
  • Navigating posts in newspaper mode leaves a little to be desired - using space to mark as read and move to the next article doesn't reposition the article to the beginning of the page.  This is useful if the article goes over the page.
  • There needs to be an option (similar to IE7) that will automatically mark all items in a feed as read once the feed has been opened.  This is one of the most useful features of IE7 IMHO - I typically scan a lot of feeds without reading every last article so I don't bother marking them all, I just let IE7 mark the entire feed as read as I navigate down the tree.

The other thing I would love to see someone build (perhaps someone has and I don't know about it) is a service that will keep multiple computers in sync.  I have two machines that I read feeds on and I find it frustrating that the "read" status is not in-sync.

Occasionally Connected Applications get a new friend

One of the topics that I'm particularly passionate about around building applications that work in both connected and disconnected mode.  I've had a bit of experience with this both at AutumnCare and now at Intilecta so I would like to think that I've encountered most of the issues that typically arise.  Typically the one that causes most headaches is how you go about synchronising data between the server and the client applications.  At AutumnCare we used webservices to pass serialized objects and changeset along the wire; at Intilecta we are using Merge replication to make our lives easier.  Now there is a new kid on the block in the form of the Microsoft Sync Services.  Although the first CTP of this has only just been released, Steve has been talking about this for quite some time.  In fact if you caught the Microsoft Developer Show late last year you will recall that we talked about what the future of occasionally connected applications might look like. 

If you are building Occasionally Connected applications (ie client applications for mobile devices, tablet pcs or UMPCs) then you should really check out the CTP which you can download here.  There is a forum and samples that you can also download.

Heat and computers don't mix

Anyone who has been in Perth over the last week or so will understand where I'm coming from - for the Australia Day long weekend (ie last weekend) we had a run of reasonably hot days (say around 40 degrees).  Now as most of you will appreciate hot temperatures and computers don't really go well together.  Unfortunately our house currently has two computers that run pretty much non-stop - we have an SBS server (thanks Wayne for the help in setting this up) and a Vista Media Center.  We also don't have air conditioning!  Here are just a few of the things that went wrong over the weekend - some of them are computer related, others are just plain frustrating.

SBS - On Saturday the machine hung and needed to be forcibly rebooted.  Since then it seems to be doing silly things like randomly locking accounts.

Vista MCE - Yesterday a whole bunch of updates were downloaded and the machine decided that it was going to automatically reboot.  Now Media Center doesn't seem to be functioning properly.

Car - Right before the long weekend my car decided that the ignition switch was going to break.  I had already ordered a new key barrel as the key was periodically getting stuck but when the switch went I threw in the towel.  Anyhow the car should be back today and my bank account a little lower.  Thank goodness to the friendly guy from the RAC who opened up the steering column and pulled out the ignition switch so that I could start the car with a screwdriver

Blog - My blog has been performing really badly so earlier this year I made the jump and upgraded the version of community server.  Unfortunately I realised later that of course not only was the database a SQL 2000 db there were also a whole bunch of inconsistencies introduced as part of my poor effort at upgrading.  I decided that I'd better recreate the database - which of course meant I'd loose all my existing posts.  Prior to doing this I used Sql Server Management Studio to do a data export (which was really quick I might add) to a local db.  After recreating the database I then used the import functionality to put all my content back into the new database.  This worked quite successfully until I realised that I was missing like half my posts.  Unfortunately what I didn't realise (until late last night) was that the import didn't maintain the correct relationships.  To cut a long story short I then spent a couple of hours sifting through the inner workings of community server working out how the tables relate.  A word of advice:  ALWAYS decide on a naming strategy that makes sense and then stick to it!!!  There seems to be too much going on with the db schema for community server and only half of it seems to make sense - this is a great pity as the product rocks.

Anyhow I've hopefully sorted these issues out and will soon be on the road to recovery.  Oh, the other thing was that I repaved my work laptop (Compaq nx8220) and installed Vista.  Vista installed without any issues, detecting and automatically installing correct drivers for everything (nice, really really nice job!!).  The machine is now humming and other than a few complains (like when is Microsoft going to fix Visual Studio and SSMS to work properly under Vista) I am one satisfied customer. 

Imagine Cup (Australia) 2007

I just noticed that in the latest Flash the Imagine Cup is getting a good rap.  In fact you can go through to the Australian Imagine Cup website which, unlike the full Imagine Cup site (well at least the last time I looked), has a feed!! (disclaimer: even on the Australian site the IE feed button still doesn't glow - you have to click on the RSS icon on the page????). Click on the following "Blog Button" to access the news/events feed.  For more information on the Imagine Cup you should check out Bernard's blog

Gaming for the Kiddies

I've often wondered how parents are supposed to teach kids about the proper use (if there is such a thing) of technology, especially when it is likely the kids are more knowledgable and learn quicker than they do.  Andrew Parsons, co-author of Professional Visual Studio 2005 (which you can still buy from Amazon here, here and here), runs a website "dedicated to helping parents and carers understand the vaue of technology". Check it out at www.gameparents.com