Beware of routed events

WPF introduces the concept of routed events. There are different routing strategies, but the most commonly used strategy is the bubbling strategy. With the bubbling strategy, the event handlers on the event source are invoked. The routed event then routes to successive parent elements until reaching the element tree root or when a handler sets the Handled property.

Always make sure that you set the Handled property, when you handle a routed event. It’s easy to forget, but the framework walks up the tree to find another handler. This has a performance penalty, but it might have unwanted side-effects that are even worse.

When you use controls that can be nested, then you should take extra care when handling routed events. Suppose we have the following code:

<Expander x:Name="Expander1" Header="Expander 1" Collapsed="OnExpander1Collapsed">
  <Expander x:Name="Expander2" Header="Expander 2">
    <TextBlock Text="Routed event test application."/>
  </Expander>
</Expander>

And we implement the Collapsed handler like this:

private void OnExpander1Collapsed(object sender, RoutedEventArgs e)
{
   MessageBox.Show("Expander 1 is collapsed.");
   e.Handled = true;
}

When you collapse Expander 1, then the message is shown. But guess what happens if you collapse the inner expander? The inner Expander raises the Collapsed event and the framework will search for an appropriate handler. The Collapsed event is defined as a bubbling event, so it will start at the source (the inner expander) and will go up the visual tree. When it reaches the outer expander, then it will call the event handler.

You can solve the problem by adding an event handler for the inner expander and set its Handled property. It works in this example, but it won’t if a third-party control raised the event. The only way to solve this problem is to check the source of the event, so the event handler should read:

private void OnExpander1Collapsed(object sender, RoutedEventArgs e)
{
  if (e.OriginalSource == this.Expander1)
  {
    MessageBox.Show("Expander 1 is collapsed.");
    e.Handled = true;
  }
}

In this example the problem is clearly visible. But things can get really nasty in more complex scenarios. Suppose you use an expander control in your code and some changes the template of another control so it uses an expander too. If this control is used within your expander, then things might get pretty nasty if you handle the Expanded and/or Collapsed events.

So make sure you check the source of the event for routed events. The disadvantage is that you have to name your control, which adds additional fields to your class. If the expander is inside a data template, then checking the name is a little bit more difficult, but not impossible:

private void OnExpander1Collapsed(object sender, RoutedEventArgs e)
{
  var originalSource = e.OriginalSource as Framework;
  if ((originalSource != null) && (originalSource.Name == "Expander1"))
  {
    MessageBox.Show("Expander 1 is collapsed.");
    e.Handled = true;
  }
}

Windows Phone 7 SDK

This Windows Phone 7 SDK has been released this week and I must say that I am impressed and disappointed at the same time. Let’s start with the positive things:

  • WP7 applications use Silverlight 4, which is a great and elegant programming model.
  • A WP7 simulator is included which works fast and easy.
  • The SDK fully integrates in VS2010.NET

The negatives:

  • It uses a subset of Silverlight 4, which lacks a lot of functionality (at this moment?). Even a simple DockPanel is not available (although this is easy to implement).
  • No local database support. There are some open-source solutions, but I would rather use something like SQL-Server for Mobile.

The programming model is much better than Apple’s Cocoa Touch framework. Silverlight is much more elegant compared to the ancient Objective-C stuff that Cocoa Touch uses. The drawback is that Apple’s system is more mature. You can access a standard database and it ships which better controls than WP7 does. Maybe things get better before WP7 ships, but there is still a lot of work to do for Microsoft.

Enable remote support for Asrock ION 330HT

I have bought an Asrock ION 330HT-BD some time ago and today I managed to get the remote working right. Now I can control XBMC with the remote and also put to to sleep and resume it again. Unfortunately, it wasn’t obvious so I describe how I enabled the remote. I used XBMC Live v9.11 (based on Ubuntu v9.10) as a starting point.

Make sure XBMC is not running, when you make changes to the system. Some commands cannot be executed when XBMC is running.

Check BIOS

The integrated IR receiver can be enabled/disabled in the system’s BIOS. The default setting is to enable the IR receiver, but make sure you check the setting. The IR receiver is called CIR in the BIOS and ACPI settings.

Install LIRC

First you need to make sure you have installed ‘LIRC’. Most distributions will install it by default, but otherwise you can enter the following command to install it:

apt-get install lirc

Make sure you have the correct version of LIRC (I use v0.8.6). You can check the version by typing the following command:

lircd --version

Install driver

Install the Asrock driver from the Asrock website. Unpack the driver and make sure you have the v1.0.1 version. The v1.0.0 driver works, but isn’t able to wake up the device when it is in sleep mode. The v1.0.2 version has issues with repeating buttons and it seems that it has been pulled from the Asrock website.

When the driver is downloaded, then you should install the driver using the following command (assuming you run a 32-bit version):

dpkg -i lirc-nct677x-1.0.1-ubuntu9.10.deb

This will install the driver and will guide you through some screens. Note that LIRC is used for IR receivers and transmitters, but we are only interested in the receiver part. In the first list, you can select the IR receiver and in the second list, you choose the IR transmitter. For the Asrock ION 330HT, you’ll need the NUVOTRON receiver and you can leave the transmitter set to ‘NONE’. Oddly enough, the first time the NUVOTRON is not in the list. Just select ‘none’ for both the receiver and transmitter and it will ask you again for an IR receiver. The second time the NUVOTRON is in the list and you should be able to use the remote from within XMBC.

Enable suspend/resume in XBMC

It’s quite convenient to use the remote to suspend/resume the device. Make sure you set XBMC power management options to suspend the device.

You should also configure the system to listen to the IR receiver while suspended to be able to resume when the remote is used again. This can be done by adding the following lines to your /etc/rc.local file:

echo CIR > /proc/acpi/wakeup    # Enable wake-up on IR receiver
echo USB0 > /proc/acpi/wakeup   # Enable wake-up on USB0 port (keyboard)

Make sure this code is executed, so I put it just below the comments that are at the top of the file. Check it by saving the file and reboot your Asrock device. When the system has rebooted, then enter the following command:

cat /proc/acpi/wakeup

It should output the following data:

Device  S-state	  Status    Sysfs node
CIR     S4        enabled   pnp:00:04
SMB0    S4        disabled  pci:0000:00:03.2
USB0    S4        enabled   pci:0000:00:04.0
USB2    S4        disabled  pci:0000:00:04.1
NMAC    S5        disabled  pci:0000:00:0a.0
PBB0    S4        disabled  pci:0000:00:09.0
HDAC    S4        disabled  pci:0000:00:08.0
XVR0    S4        disabled
XVR1    S4        disabled
P0P5    S4        disabled
P0P6    S4        disabled
P0P7    S4        disabled
P0P8    S4        disabled
P0P9    S4        disabled

When you press the ‘ON/OFF’ button on your remote (upper right), then the Asrock should suspend if you have XBMC running (the blue led will flash). When pressing the ON/OFF button again, then it should resume again.

Re-initialize remote in XBMC

When the Asrock resumes, then the IR drivers need to be reloaded and XBMC must be notified. Create a new file called /etc/pm/sleep.d/99lirc-resume.sh with the following content:

#!/bin/sh

# This script uses curl. Install curl using the following command from your terminal apt-get install curl
# This script will restart lirc drivers, Lirc, and XBMC's lirc interpreter upon resume.

# Make sure you also use the LIRC_WB677 driver. You can check which driver is loaded by typing 'lsmod'.
lircDriver=lirc_wb677

case "$1" in
    resume)
        curl "http://127.0.0.1:8080/xbmcCmds /xbmcHttp?command=ExecBuilt&Inparameter=LIRC.Stop"
        /etc/init.d/lirc stop
        rmmod $lircDriver
        modprobe $lircDriver
        /etc/init.d/lirc start
        #remove the comment if the computer automatically sleeps after resume
        #irw & sleep 1; killall irw
        curl "http://127.0.0.1:8080/xbmcCmds/xbmcHttp?command=ExecBuiltIn&parameter=LIRC.Start"
        echo "lirc resume script completed!!!" >>/tmp/script.log
    ;;
esac

Make sure the script can be executed by entering the following command:

chmod 755 /etc/pm/sleep.d/99lirc-resume.sh

Some older examples that use the non-HT version of the Asrock use a different driver, so make sure your driver is correct.

WPF Control Development Unleashed

Readers of the blog might think I am only working on iPhone stuff, but in fact I am programming WPF for 40 hours a week. I am glad, because C# / WPF is a lot better then Objective-C / Cocoa Touch.

WPF Control Development Unleashed

Last week I got the latest book of SAMS publishing about WPF. I did recommend the Windows Presentation Foundation Unleashed before, but now they have a new book. It’s called WPF Control Development Unleashed.

The previous book is still the best book out there, if you want to get started on WPF development. If you’re already an experienced WPF developer and develop your own WPF controls or use advanced layout scenarios, then the new book is for you. I am an experienced WPF developer (over two years 40 hours/week pure WPF programming), but there was enough in this book to pay $50 for it.

When you’re serious about WPF programming and think you know already a lot about it, then you should order this book right away.

Create applications for the iPhone

I little while ago I figured out how to disable A2DP on my iPhone. It requires some changes to property lists, which requires additional tooling and makes it less accessible to less experienced users. If it was a Windows based device, then I would have created an application to make the changes. So why not do this for the iPhone?

The iPhone also has a compiler and SDK, but it uses the Objective C language and the Cocoa Touch framework. I am used to Windows programming for the last 15 years and I can tell you that iPhone development is completely different. I bought two books that got me started on Objective C and iPhone development:

Useful books

Title: Learn Objective-C on the Mac
Author: Mark Dalrymple & Scott Knaster
ISBN: 978-1-4302-1815-9

This book describes all the aspects of Objective-C. I think it is a little verbose and when you already familiar with object-oriented programming, then you probably want to skip a lot of details. I bought it, because I wanted to make sure I didn’t miss anything. Make sure you know Objective-C, because it’s not just a different C++ dialect.

Title: Beginning iPhone 3 Development: Exploring the iPhone SDK
Author: Dave Mark & Jeff LaMarche
ISBN: 978-1-4302-2459-4

I first downloaded a PDF version of this book via a torrent site and liked it so much that I decided to buy the (updated) paper version of the book. It describes iPhone development from the ground up, so it’s a good starter for iPhone development. It describes all the common controls and views that are used in iPhone applications. I am not a Cocoa expert, but I think that if you are then this book is not for you and you should look for a bit more in-depth book.

Get the right tools

Developing iPhone applications is only possible on Mac OS X, so you need an Apple computer. The standard development environment is called Xcode. You need to obtain an Apple Developer Connection membership to be able to download Xcode. The online membership is free, so make sure you register.

Once you have been registered, then you should download and install Xcode. Make sure you download the right version. If you are running OS X v10.5 you need to download Xcode v3.1.x. Snow Leopard users (OS X v10.6) need Xcode v3.2.x. This is all you need to develop software for Mac OS X, but it doesn’t contain the iPhone bits. Go to the iPhone section on the developer website and download the iPhone SDK.

This is all you need to create iPhone applications and test the applications in the iPhone simulator.

Test application on your own iPhone

Once you are ready developing and testing your application in the simulator, then you need to test it on your own iPhone. You can enroll in the iPhone Developer Program, which will cost you at least $99. If you plan to put the application in Apple’s AppStore, then you need to do this. There is no other way to get your application in the AppStore.

My application will not be approved in the AppStore, because it changes system settings and this is not allowed or possible from applications in the AppStore. My application will be distributed via Cydia (only for jailbroken iPhones). You don’t need to enroll for the iPhone Developer Program, but you need to make some modifications to your Xcode installation to make sure you can sign your application.

Obtain a code signing identity

You need to obtain a code signing identity. Fire up Keychain Access and choose Keychain Access – Certificate Assistant – Create a certificate… and use the following settings:

KeyChain

Note that you create a certificate with the name iPhone developer for code signing and you want to override defaults. Click continue and accept the defaults (although you can change your email address). Make sure the certificate is stored in your login keychain.

Patch Xcode v3.2 to deploy

There are two ways to patch Xcode to allow the application to be build. This first method is to patch Xcode v3.2 to be able to sign applications without a provisioning profile (note that this patch is only valid for v3.2!!!):

#!/bin/bash
cd /Developer/Platforms/iPhoneOS.platform/Developer/Library/Xcode/Plug-ins/iPhoneOS\ Build\ System\ Support.xcplugin/Contents/MacOS/
dd if=iPhoneOS\ Build\ System\ Support of=working bs=1 count=300752
printf "\xc8\x2f\x00\x00" >> working
dd if=iPhoneOS\ Build\ System\ Support of=working bs=1 skip=300756 seek=300756
/bin/mv -n iPhoneOS\ Build\ System\ Support iPhoneOS\ Build\ System\ Support.original
/bin/mv working iPhoneOS\ Build\ System\ Support
chmod a+x iPhoneOS\ Build\ System\ Support

Another approach seems more elegant. Create a backup of /Developer/Platforms/iPhoneOS.platform/Info.plist and modify the Info.plist by replacing the two occurrences of XCiPhoneOSCodeSignContext with XCCodeSignContext.

Update project settings for code signing

Application signing Project – Edit Project Settings, select the Build tab and find the Code signing section. Select the Code Signing Identity. At the lower left part of the dialog, there is a popup menu and you should select the Add Build Setting Condition. Change the Any SDK to Device – iPhone OS 3.0. Select the iPhone developer certificate in the right column. If it doesn’t show up, then you didn’t create a proper certificate. The screen below shows the correct settings:

ProjectSettings

Sign your application

Applications on the iPhone need to be signed. You can use the official Apple signing method, which is pretty complicated, or use Saurik’s pseudo-signing method. In this tutorial I will use the pseudo-signing, because it’s easy and codesign checking has been hacked out of the jailbroken kernels anyway. There are two ways to pseudo-sign your application:

  1. Sign the applications on the iPhone itself. SSH to your iPhone and run apt-get install ldid. This will install the ldid utility in the /usr/bin directory. After you have copied your executable to the iPhone, then you need to run ldid -S <ProgramName>. This will sign the application, so you can run it.
  2. Sign the application on your Mac. Download ldid from TheBigBoss site to /usr/bin. Make sure that you can execute it (chmod 755 /usr/bin/ldid). Make sure you sign you applications at the end of the build process. In XCode select Project – New Build Phase – New Run Script Build Phase and use the following script:

    /usr/bin/ldid -S $TARGET_BUILD_DIR/$TARGET_NAME.app/$TARGET_NAME

If you forget to sign the application, then your application will crash immediately after starting.

Create a deployment package

I could have copied the text on Saurik’s website, but if you look here then you find everything that you need to create packages to deploy you application. After transferring the package to your iPhone, then you can install it using dpkg -i package.deb. You need to refresh your springboard to make sure the application is shown on screen. I use gUICache (available through Cydia) to refresh. Cydia refreshes automatically, after you (un)install a package.

Submit the application to a repository

When your application is ready, then you probably want to release it. You need to host the application via a repository, such as TheBigBoss.org. This repository is available in most Cydia configurations, so you are sure that users with a jailbroken iPhone can find your application. You need to have a Debian compliant package and need to fill in a form. The application will be hosted in the repository within 24 hours.

Resources