Dutton's blog

How to fix the iTunes 10 compilation album grouping bug

I've been encoding a lot of my CDs in iTunes (10.1.2) lately. It generally does a great job of encoding to Apple Lossless and grabbing the appropriate track data and cover art from the internet I've have come across an annoying problem. Occasionally, despite ALL of the tags being the same, and numerous combinations of "Compilation, Sort Album, etc..." being set, iTunes still insists on listing a compilation album as individual tracks like this:

A google search of the problem shows that I'm not alone. There seems to be as many solutions as there are people posting so in case it's of any use, here's what has worked for me every time.

  1. Select all of the tracks you wish to group, right-click, and from the context menu select "Get Info".
  2. On the "Info" tab, enter a single space in the "Album Artist" field.
  3. On the "Options" tab, set "Part of a compilation" to "Yes".
  4. Click "OK" to make those changes.
  5. The album should now be grouped properly, and you'll see something like this:
  6. The only problem is now iTunes thinks that the album's artist is " " and so isn't listing it as "Various Artists", so with the tracks selected, right-click and from the context menu select "Get Info" again.
  7. This time on the "Info" tab, remove the single space from the "Album Artist" field.
  8. Click "OK" to make that change and the album should now be grouped properly and listed as Various Artists.
DoshTracker Update #5 – 16 months later...

It has been a while, but not completely quiet on the DoshTracker front. Although last year my Project 365 took up most of my free time, I have been slowly working on another UI design using a new Javascript framework (jQuery) and this time it's really coming together.

We have:

  • Full Google Maps interaction, plotting all our note hits on a map.
  • International support, now you can plot your notes anywhere the Google Maps API can geocode.
  • The complete old database! All of your original DoshTracker notes and user accounts have been preserved. These will be imported during the beta.

Check out the new logo and design on www.doshtracker.co.uk and please sign up for our mailing list so we can keep in touch.

Invites to the closed beta test will be going out soon to the mailing list and former users of the old site.

How to find the Hash key on a UK Mac Keyboard
I'm a Microsoft .Net programmer by day and yet a Mac user by night, but occasionally I still need to type the '#' key on my UK Mac keyboard and always forget the shortcut as it's not immediately apparent. I usually end up copying and pasting it from somewhere else.
It's ALT-3, #########, there!
OK - Cancel behaviour with data binding in WPF

As much as I am a fan of the Mac OSX and iPhone approach of modifying a setting and having it apply immediately without any further user interaction, my current work involves designing GUIs for Industrial Control and Automation systems where the old <OK> <Cancel> buttons are still required (often by law) which brought up the question of how to do this in WPF with data binding where, depending on the control, updates are triggered either in real-time or on loss of focus.

The answer is in one of the attributes of Binding called "UpdateSourceTrigger" which has the following options:

  • LostFocus - Update bound property when the control loses focus (TextBox default).
  • PropertyChanged - Update bound property in real-time.
  • Explicit - Update bound property when UpdateSource() is called

It is this last setting which allows us to delay updating our bound property until we tell it to.

Let's say we have a UserControl containing a TextBox, 'MyTextBox' which is bound to some Dependency Property and two buttons, 'OK' and 'Cancel'. Depending on how you hook your buttons up (with RoutedCommands or click handlers (eugh!)) the 'OK' button's code looks like this:

BindingExpression be = MyTextBox.GetBindingExpression(TextBox.TextProperty);
if (be!=null) be.UpdateSource();

The 'Cancel' button's code does the reverse:

BindingExpression be = MyTextBox.GetBindingExpression(TextBox.TextProperty);
if (be!=null) be.UpdateTarget();

Et voila! Your dependency property will now only update when you want it to.

Handling events from within a ControlTemplate in WPF

Here's an interesting one that had me stumped for a few hours.

Following on from my previous post, where I explained how to create a ControlTemplate to style a TextBox in WPF, I've got an object, TextEntryBox, which dervies from a TextBox (it provides some custom event handlers when text is entered, but to all intents and purposes, it's a regular TextBox).

I wanted to style my TextEntryBox, this time including a button within my ControlTemplate (this will eventually toggle an on-screen keyboard pop-up, but that's another blog post!). I came up with this:


All's well and good, until I want to try and handle the Click event for that button within my TextEntryBox class. Even Matthew MacDonald's "Pro WPF in C# 2008" which has proved a lifesaver for all things WPF since I've been working with this technology only had the following words of wisdom;

"You can't attach event handlers in the control template. Instead, you'll need to give your elements recognizable names and attach event handlers to them programmatically in the control constructor"

But whatever I tried I couldn't access the event in my constructor, until I remembered the seperation between the visual and logical trees in WPF.

The template is applied at runtime, and so elements contained within it it are part of the visual tree. My class, and therefore my class' constructor is executed within the logical tree, so I needed to attach my event handler after the template had been applied. You can do this by overriding OnApplyTemplate in your class, obtain the template that's being applied, and then you have access to the named button's events, like this:

public override void OnApplyTemplate()
{
    DependencyObject d = GetTemplateChild("PART_KeyboardPopupButton");
    if (d != null)
    {
        (d as Button).Click += new RoutedEventHandler(KeyboardPopupButton_Click);
    }