RSS 2.0
# Monday, July 16, 2007

Here we are on the 10th installment of what I thought would be a pretty simple walk-through into writing standard, distributable applications using WPF. This walk-through started out mirroring the old Scribble tutorial (http://msdn2.microsoft.com/en-us/library/aa314520(VS.60).aspx) but has recently turned into me complaining about things I don't understand very well. Specifically, I'm just not getting my head around the localization story with WPF and how it interacts with the built-in ApplicationCommands.X classes and keyboard access (mnemonics in  MFC). So, rather than complaining, let's just solve the problem.

The problem is this: ApplicationCommands.X classes give the developer a nice, automatically localized hook to use in hooking up UI elements to business logic to be executed. These commands are automatically localized based on the currently selected UI culture. These commands don't have access keys for use in MenuItem UI elements, so if I use the ApplicationCommands.New command in the file menu, I can't invoke it via Alt+f,s (something I've been doing from the old DOS days and am not interested in changing).

Solution 1 -- Implementing our own ScribbleCommands class from scratch

Here's a possible example. We could just implement our own ApplicationCommands-like class to serve up all of the commands we're interested in using from the UI. After all, we already implemented ScribbleCommands.Exit, so we can do something like that for the rest of the commands. This has the downside of requiring us to localize all of the text ourselves.

Solution 2 -- Implementing our own ScribbleCommands class as an adapter around ApplicationCommands

This is the one we're going to pursue. Since we already have ScribbleCommands and since MS already gives us much of the plumbing for the built-in commands classes, we'll just enhance that built-in functionality to convince it to do what we want. Here's the idea: for commands that don't have built-in ApplicationCommands.X implementation, we create string resources for all UI related aspects of the command (Name, Text, Gextures, Gesture display text, Tooltip, and Description). For commands that do have a built-in ApplicationCommands.X implementation, we create string resources for the bits of UI related aspects we want to override (mnemonic character, Tooltip, and Description).

The Scribble.Exit command looks like this:

public static RoutedUICommand Exit
{
	get
      {
      	return EnsureCommand(
			Properties.Resources.ExitName,
			Properties.Resources.ExitText,
			Properties.Resources.ExitGestures,
			Properties.Resources.ExitGesturesDisplayText);
	}
}
public static string ExitTooltip
{
	get
	{
		return Properties.Resources.ExitTooltip;
	}
}
public static string ExitDescription
{
	get
	{
		return Properties.Resources.ExitDescription;
	}
}

The Scribble.New command looks like this:

public static RoutedUICommand New
{
	get
	{
		RoutedUICommand command = ApplicationCommands.New;
		string commandText = command.Text;
		int accessIndex = 
			commandText.IndexOf(Properties.Resources.NewAccessKey);
		if ((accessIndex >= 0) && (commandText.IndexOf('_') < 0))
		{
			command.Text = commandText.Insert(accessIndex, "_");
		}
		return command;
	}
}
public static string NewTooltip
{
	get
	{
		return Properties.Resources.NewTooltip;
	}
}
public static string NewDescription
{
	get
	{
		return Properties.Resources.NewDescription;
	}
}

Notice, we have to use our own Tooltip and Description properties here since the built-in commands don't have these items provided. Also, notice we are searching the returned command.Text for a pre-existing _ character. This is so we don't forcibly overwrite any mnemonic that may already be set. Of course, you could just remove it instead.

Using any of these commands in the UI looks exactly the same as before

<MenuItem Command="{x:Static scribble:ScribbleCommands.New}" />

There it is. The code (in Spanish and English) is available at http://www.cavinconsulting.com/Code/Scribble10.zip. To run it in Spanish, just un-comment the marked lines in App.xaml.cs. If you're running Windows XP, be sure to install the Spanish language pack for the .NET 3.0 Framework (http://www.microsoft.com/downloads/details.aspx?FamilyID=41c61d2a-d411-4dde-9013-bb08eb688bb6&DisplayLang=en). Unfortunately, if you're running Vista, it isn't as simple as just installing the language pack. If you have Ultimate or Enterprise edition, you should see the language packs on Utimate Updates. I didn't, however, and ended up downloading it directly from here.

I'm still not sure what I think about this approach. It does salvage the automatic localization provided by the runtime. It allows each language to define their own mnemonics or to fall back on the default mnemonic (if the latter exists in the command). However, on windows Vista, the localization only appears supported on Ultimate or Enterprise editions, and the installation of the appropriate MUI packs doesn't seem as simple as the old language pack model. Also, it limits my target audience to only those fortunate enough to be running an expensive version of Windows.

Monday, July 16, 2007 9:39:29 PM (Pacific Standard Time, UTC-08:00)  #    Comments [0] -
WPF
# Friday, July 06, 2007

Up to this point, we've been concentrating on the infrastructure aspect of what it takes to make a "standard" application using WPF. We aren't quite there yet. The localization story for WPF applications is pretty fuzzy as is the keyboard accessibility framework. More importantly, getting the two to work together is questionable, at best.

The story so far:

WPF makes heavy use of the Command pattern for hooking execution logic to different UI elements. The WPF framework provides us with a number of built-in commands for our use (like ApplicationCommands.New, and EditingCommands.AlignCenter. Here are my impressions on using these commands out of the box:

The Good

  • UI elements which are "command aware" can have many of their properties localized to the current UI culture without the programmer having to do anything.
  • Having so many canned commands makes it all the more likely that developers will actually use the command pattern for their own commands.
  • Most commands are decorated with commonly KeyGestures so things like Ctrl+C or Shift+Delete invokes the ApplicationCommands.Copy command without the programmer having to do anything.

The Bad

  • The localized commands do not have a method (that I have found) to designate a mnemonic (now called an access key) for easy, localizable keyboard access inside a MenuItem. So, I haven't found a way to attach the ApplicationCommands.Save command to an item under the _File MenuItem and have the key sequence Alt+f,s invoke the save command. This is a big problem for me because I routinely use Alt+f,s to save rather than Ctrl+s. I may be the only one in the world, since it's a throwback to the old DOS editor, but I still use it.
  • There doesn't seem to be a really friendly way to extend or specialize the built-in commands overriding just the information you want to specialize. Instead, I resort to duplicating the built-in command, thereby loosing the automatic localization capabilities.

The localization story in WPF is also a little confusing to me. What with all of the different types of resources available (resource dictionaries in App.xaml, and Window.xaml along with the standard Properties.Resource available in .NET 2.0) it is unclear to me how a developer is expected to make robust, localizable applications. So far, I have encountered several discussions on how it can be done, but most of them rely on a pretty flimsy example application (LocBaml), this article http://msdn2.microsoft.com/en-us/library/ms753931.aspx and some clumsy hand-editing of both ApplicationSettings.cs and the .csproj file. Moreover, the localization mechanism is by way of replacing the localizable strings in a .csv file. What happened to the localizable resource editor we had in MFC 10 years ago? Moreover, we already have a mechanism for localizing resources for a .NET 2.0 application. Ultimately, the Baml information just gets stored as a localizable resource in the executable. Why is there no tool support here?

To be fair, I'm sure Microsoft hasn't forgotten that agencies other than Microsoft produce multi-cultural applications. On the contrary, I'd like to think that easy localization of an application is very important to Microsoft. However, I'm just not seeing that coming out of their new toolsets. It doesn't look like there will be anything of the sort in the Orcas timeframe either.

Why all the fuss? I started this project out simply trying to create a "generic" desktop application using the WPF framework. By generic, I mean just what the original MFC Scribble tutorial was -- a simple, standard, Windows application with all of the appropriate Windowsy goodness like tooltips, keyboard access, shortcuts, and localization. When it comes down to it, writing such an application in WPF appears to be a lot more work than I think it should be.

I still plan on pursuing this project as I think it is important that developers understand the importance of a "standard" look and feel even though our new toolsets open up the possibility to diverge from that standard (or create a new one). Also, I think it is always important to remember that there are other languages besides English. By remembering this, and designing for it, we can ensure the ability to localize our applications for markets we may otherwise be ineligible to join.

Friday, July 06, 2007 9:38:56 PM (Pacific Standard Time, UTC-08:00)  #    Comments [0] -
WPF
Navigation
Categories
About the author/Disclaimer

Disclaimer
The opinions expressed herein are my own personal opinions and do not represent my employer's view in any way.

© Copyright 2012
Cavin Consulting
Sign In
Statistics
Total Posts: 28
This Year: 0
This Month: 0
This Week: 0
Comments: 4
All Content © 2012, Cavin Consulting
DasBlog theme 'Business' created by Christoph De Baene (delarou)