January 2010 - Posts

It’s basically Dances with Wolves in space, and it has

  1. Spaceships
  2. Aliens
  3. Boobs
  4. Giant robots
  5. Soldiers
  6. Horses
  7. Dragons
  8. Energy weapons
  9. Exotic wildlife
  10. Exciting chase scenes
  11. Lots of explosions
  12. State of the art CG
  13. Noble savages
  14. Elves (the noble savages are tall and slender with pointy ears, and run around communing with nature)
  15. A soppy doomed-love story
  16. Resurrection themes

All the good-guys are attractive and smart. All of the annoying characters get killed.

Posted by peterw | with no comments

BusyIndicator is your friend

Let me begin by stating the obvious: if you bind your UI to one or more DDSs (DomainDataSources) then when the UI renders it will fetch values from those DDSs. Now let me ask you a question: if you hover the mouse over a grid, will that cause data to be fetched? You can guess that it does, from the mere fact that I’ve posed the question. But how can this be?

With the default stylesheet, and indeed most stylesheets, the DataGrid and other widgets are thoroughly littered with triggers that respond to mouse activity. This of course is what makes Silverlight the out-of-box multimedia extravaganza that it is, and we wouldn’t have it any other way. But it does mean that the mere proximity of a mouse pointer triggers rendering, which in turn fetches data. If the DDS involved isn’t ready this can produce unsightly exceptions that quite spoil the UX.

So what’s a girl to do?

Use a BusyIndicator, that’s what.

I can’t think of a scenario in which you wouldn’t add a BusyIndicator as the outermost widget in your Visual Tree. If you don’t do binding then it’s harmless, and if you should plonk a data-bound widget on your page or window then it’s there waiting to monitor IsBusy on any and every DDS that becomes its child, preventing user interaction until they become ready.

This disabling of UI until all the DDSs are ready sorts out a variety of issues:

  • It no longer matters in what order DDSs become ready, because combo-boxes and other Selector derivatives won’t try to fetch from lookups till they render.
  • Mouse activity no longer triggers UI activity cascading into premature fetches.

What happened to AutoBind?

AutoBind, for the great unwashed, is or rather was a Boolean property which when set to True would cause the BusyIndicator to find all its child DDSs and behave as though IsBusy were bound to the OR of all the DDS IsBusy properties, so any DSS becoming busy would lock the UI.

Sound good? According to this blog post, AutoBind was removed for performance reasons.

A workaround

Here’s how to efficiently provide the same behaviour using very little code.

First, synthesise a value from your various DDSs by creating a page property.

  172     public bool IsBusy

  173     {

  174       get

  175       {

  176         return assetDomainDataSource.IsBusy

  177           || assetGroupDomainDataSource.IsBusy

  178           || contactDomainDataSource.IsBusy

  179           || deviceDomainDataSource.IsBusy

  180           || employeeDomainDataSource.IsBusy

  181           || employeeGroupDomainDataSource.IsBusy;

  182       }

  183     }

Notice that each DDS already has an event handler for its _LoadedData event. You don’t need five identical handlers. Delete all of them and paste this instead.

  156     private void LoadingData(object sender, LoadingDataEventArgs e)

  157     {

  158       busyIndicator1.IsBusy = IsBusy;

  159     }

  160 

  161     private void LoadedData(object sender, LoadedDataEventArgs e)

  162     {

  163       busyIndicator1.IsBusy = IsBusy;

  164       textBoxSearchTerm.Focus();

  165       if (e.HasError)

  166       {

  167         System.Windows.MessageBox.Show(e.Error.ToString(), "Load Error", System.Windows.MessageBoxButton.OK);

  168         e.MarkErrorAsHandled();

  169       }

  170     }

Now go through your XAML and fix up your DDSs so they refer to the two handlers you just pasted in. The quickest way to do this is to use Edit/Replace with wildcards like this:

image

I suggest you also gather all your RIA declarations together, and put them in load dependency order. This is not strictly necessary, but it’s easier to check whether you have everything when the code is orderly.

If you try to run this it will probably barf on this line of code.

  164       textBoxSearchTerm.Focus();

Your page probably doesn’t contain a TextBox named textBoxSearchTerm. I left this in to point out that if there’s a control you’d like to focus when the data finishes updating then this is a pretty good spot to do the deed. Just remove the whole line if you don’t want to interfere with focus.

How it works

Whenever a DDS starts loading data, the page IsBusy property will return true. With subsequent load starts this property will continue to return true. When a DDS finishes loading, the page IsBusy will only return false if none of the DDSs are busy, so the BusyIndicator will remain visible until the last DDS finishes loading – exactly the desired behaviour, completely event driven and with less code than the designer generates.

I’d like to see the designer do this automatically, but I doubt the VS team would consider it. Perhaps someone with experience creating Visual Studio Addins might help.

Posted by peterw | with no comments

CopySourceAsHtml is a Visual Studio Add-in originally from JTLeigh and Associates, now available from Codeplex. Although testing is not complete it does seem to work with the beta of VS2010, and a patched MSI is available from http://copysourceashtml.codeplex.com/SourceControl/PatchList.aspx

However, Copy As HTML is conspicuously absent from the context menu for the XAML editor. To correct this, follow these steps:

  1. Right-click on a toolbar and choose Customize…
  2. Select the Commands tab.
  3. Select the Context menu radio button. This will enable a combobox.
  4. From the combobox, select Editor Context Menus| XAML Editor. This will show the items in that context menu.
  5. Scroll down and select Copy.
    image
  6. Click the Add Command… button. This will open the Add Command dialog.
  7. Select Addins from the list of categories. This will show the list of commands available from add-ins, which should contain four items from JTLeigh.
  8. Select JTLeigh.Tools.Development.CopySourceAsHtml.Connect.CopyNow and click the OK button. This will cause CopyNow to appear just above Copy in the context menu but for some reason it will end up just before Run… 
  9. You can also click the Keyboard… button and set up a keyboard shortcut.
  10. Click the Close button.
Posted by peterw | with no comments

2D map
2D map view
2D view
3D map
3D map view
3D view
Add favourite
Add to favourites
Avoid roadblock
Brightness down
Brightness up
Calculate alternative
Calculate an alternative route
Calculate original
Calculate the original route
Call
Call back
Call home
Clear route
Continue itinerary
Correct map error
Current location
Day view
Daytime view
Decrease brightness
Decrease volume
Increase brightness
Increase volume
Map error
Mark as favourite
Mark map error
Mark safety camera
Minimise delays
Minimise traffic delays
Navigate home
Navigate to a city centre
Navigate to a favourite
Navigate to a postcode
Navigate to a recent destination
Navigate to an address
Navigate to home
Navigate to the nearest camping ground
Navigate to the nearest campsite
Navigate to the nearest car park
Navigate to the nearest car repair service
Navigate to the nearest cash dispenser
Navigate to the nearest cash machine
Navigate to the nearest dentist
Navigate to the nearest doctor
Navigate to the nearest hospital
Navigate to the nearest hotel
Navigate to the nearest parking garage
Navigate to the nearest petrol station
Navigate to the nearest pharmacy
Navigate to the nearest police station
Navigate to the nearest post office
Navigate to the nearest railway station
Navigate to the nearest rest area
Navigate to the nearest restaurant
Navigate to the nearest tourist information office
Navigate to the next itinerary destination
Night view
Nighttime view
Phone
Phone back
Phone home
Read aloud traffic info
Read aloud traffic information
Read traffic info
Read traffic information
Recalculate original
Recalculate the original route
Redial
Repeat instruction
Report safety camera
Safety camera
Sound off
Sound on
Start itinerary
Travel via a city centre
Travel via a favourite
Travel via a postcode
Travel via a recent destination
Travel via an address
Travel via home
Travel via the nearest camping ground
Travel via the nearest campsite
Travel via the nearest car park
Travel via the nearest car repair service
Travel via the nearest cash dispenser
Travel via the nearest cash machine
Travel via the nearest dentist
Travel via the nearest doctor
Travel via the nearest hospital
Travel via the nearest hotel
Travel via the nearest parking garage
Travel via the nearest petrol station
Travel via the nearest pharmacy
Travel via the nearest police station
Travel via the nearest post office
Travel via the nearest railway station
Travel via the nearest rest area
Travel via the nearest restaurant
Travel via the nearest tourist information office
Turn brightness down
Turn brightness up
Turn down brightness
Turn down volume
Turn off sound
Turn on sound
Turn sound off
Turn sound on
Turn up brightness
Turn up volume
Turn volume down
Turn volume up
Use day colours
Use night colours
Volume down
Volume up
Weather report
What is the weather?
Where am I?
Zoom in
Zoom out

Posted by peterw | with no comments