Saturday 8 December 2012

A blast from the past

This morning, I noticed that my lovely web hosts 1and1 had managed to break parts of my website that had been running the day before.

It turned out they’ve planned to discontinue all versions of php before 5.4, and some of my .htaccess files had these lines included

AddType x-mapp-php4 .htm

or

AddType x-mapp-php5 .htm

These lines caused the apache server to interpret .htm files with either php 4.x or php 5.2

Now it turns out that they’ve made it x-mapp-php6 to interpret the files as 5.4

However, that’s not the reason for this post.  The real reason, is I navigated to some of my webpages that had java on them to render the help table of contents, like

http://www.metstats.com/help/

When I navigated there with my browser, I got a DEP error, and crashed internet explorer.  How odd I thought.  It works in Chrome (telling me Java isn’t installed).  After the recent round of security issues I thought I’d be better off without Java, and uninstalled it.

So off to the event viewer:

Faulting application name: iexplore.exe, version: 9.0.8112.16455, time stamp: 0x507284ba
Faulting module name: msjava.dll, version: 5.0.2752.0, time stamp: 0x35747274
Exception code: 0xc0000005
Fault offset: 0x000c5a6c
Faulting process id: 0x299c
Faulting application start time: 0x01cdd53a1a8e7151
Faulting application path: C:\Program Files\Internet Explorer\iexplore.exe
Faulting module path: C:\Windows\system32\msjava.dll
Report Id: 588d3e4c-412d-11e2-b9b6-001167d3ed60

msjava.dll faulted?  That’s so 1999.  In fact it was discontinued in 1999

http://www.microsoft.com/About/Legal/EN/US/Interoperability/Java/Default.aspx

So, why is java still on my machine when I removed it.  Searching Programs and Features, I found Microsoft VM for Java

I suspect this was installed by a very old copy of Visual Studio I still have around for supporting old software, but as I never did Java, I decided that could go.

But on installation, I found this humorous warning:

Java

I have to admit, I don’t think I need to worry about that particular loss…

Now rebooted and uninstalled, and IE crashes no more.  Who knows how many more security issues were present though.

Tuesday 20 November 2012

DateTime.ParseExact can be misleading

Last night, I was made aware of a crash in our Payslips for PAYE Tools program that occured pretty much every time it ran.

It turns out the user had changed the short date format on their system, so it included either a . or a – as the separator.

I had this line in my code:

Date = DateTime.ParseExact(value, "dd/MM/yyyy", null);

While this looks like it might do the right thing, it turns out it doesn’t as I didn’t use the invariant culture for the conversion.  The word exact is a bit misleading, as I’d assumed (incorrectly) that / was a character.  In fact, it’s replaced with the date separator, and no longer matches the string that came out of the database with a /

Tuesday 13 November 2012

Be very careful saving data in Windows 8

Windows 8 presents a number of new challenges for developers.

My challenge today is how can I save what the user is doing, and not lose it.

Best practice for Windows 8 apps suggests you save early, and often.  From the time a user closes your app you have about 10 seconds until it’s definitely not running.  For those of you who aren’t totally up to speed on the details of the Windows Store Application Lifecycle I suggest you have a look here first.

Now, the problem is in that article, on the section on App Close

App close

Generally, users don't need to close apps, they can let Windows manage them. However, users can choose to close an app using the close gesture or by pressing Alt+F4. You can't include any UI in your app to enable the user to close your app, or it won't pass the Store certification process.

Given the above, you can see that there is no way to be notified of a close event, however your OnSuspending event will still fire, after about 5 seconds.

So, assuming you busily began to save when you’re app received the VisibilityChanged event, you have maybe 5 seconds left to save the remainder of your state when you get to OnSuspending.

I say maybe, because, if you’re really unlucky, you’ll find that the user restarted your application from the start menu, after beginning your OnSuspending code.  In that case, your currently running thread will be terminated and your app will restart.  The file you were in the middle of saving could now be in any state.

If you don’t believe me, you can read the details here

Saving the application data to file in the Application.OnSuspending method does not work?

In a nutshell, this quote from the bottom of the thread sums up the problem
"To summarize, if the user closes the app and then immediately restarts before the first instance has finished closing then the first instance is forcibly terminated so the user runs in a clean state."

So, how do we build an application to demonstrate the problem?  First, in App.xaml.cs, wire up the VisibilityChanged event when you create your root frame.

Window.Current.VisibilityChanged += Current_VisibilityChanged;
this.Suspending += OnSuspending;

Next, implement the event handler like this and add a couple of members.


Task currentSaveTask;
void Current_VisibilityChanged(object sender, WIndows.UI.Core.VisibilityChangedEventArgs e)
{
if (!e.Visible && currentSaveTask == null)
{
CurrentSaveTask = SaveOurData();
}
}
async Task RenameFile(string tempFile, string newName)
{
StorageFolder localFolder = Windows.Storage.ApplicationData.Current.LocalFolder;
StorageFile sf = await localFolder.GetFileAsync(tempFile);
await sf.RenameAsync(newName, NameCollisionOption.ReplaceExisting);
}

async Task WriteData(string filename, string content)
{
StorageFolder localFolder = Windows.Storage.ApplicationData.Current.LocalFolder;
// on my machine, this is C:\Users\Tony\AppData\Local\Packages\2da24013-8fd9-49f2-8067-778dece884d6_6j3fz8tfj8x4m\LocalState

StorageFile sf = await localFolder.CreateFileAsync(filename, CreationCollisionOption.ReplaceExisting);

using (Stream s = await sf.OpenStreamForWriteAsync())
using (TextWriter output = new StreamWriter(s))
{
output.WriteLine(content);
}
}

async Task BeginSaving()
{
await WriteData("startup.txt", "We started saving");
}

async Task ContinueSaving()
{
await WriteData("temporary.txt", "The data file is incomplete");
}

async Task FinishSaving()
{
await WriteData("temporary.txt", "The data file was written successfully");
}

async Task SaveOurData()
{
await BeginSaving(); // show some progress to the user.
await Task.Delay(5500); // simulate extra work
await ContinueSaving();
await Task.Delay(4000); // simulate still more work.
await FinishSaving();
await RenameFile("temporary.txt", "final.txt");
currentSaveTask = null; // remove reference to our pending save
}


This writes a file in to our local storage, named startup.txt, and then delays long enough to guarantee we’re in the Suspend code, it then creates a file temporary.txt, delays a little longer, and finally writes the finished version of the temporary.txt file.


Finally it proceeds to rename the file to final.txt, and cleans up the handle to the outstanding task.


Now implement our OnSuspending handler like this:


 


async private void OnSuspending(object sender, SuspendingEventArgs e)
{
var deferral = e.SuspendingOperation.GetDeferral();
if (currentSaveTask != null) await currentSaveTask;
// you may want to use Task.WhenAll here to rendezvous multiple tasks...
// Task[] OutstandingSave = new Task[] { currentSaveTask };
//if (OutstandingSave[0] != null)
//{
// await Task.WhenAll(OutstandingSave);
//}
deferral.Complete();
}


This code waits for the currentSaveTask we kicked off if it exists.





Testing


To test this, do the following.


Fire up your app, and and open a window to wherever your App’s StorageFolder.LocalFolder resolves to.


Now press F4 on the app, to close it.


You should see a startup.txt file appear, followed after about 5.5 seconds a temporary.txt file appear. When you see that appear, quickly press the windows key, and click to restart your app.


You’ll notice that the remainder of the code never executes, and when you examine temporary.txt, it will contain “The data file is incomplete”.


Takeaway


If you were saving directly to a file (in XML format) and hadn’t yet completed by the time you relaunched, your file would be incomplete or corrupt.  This method allows you to check that the temporary.txt file does not exist at startup.  If it does exist, you can be pretty certain that final.txt file is incomplete.  Of course, temporary.txt file may be incomplete as well, so you’ll need to code in an additional step to allow you to check that it too is complete, (possibly by renaming to another intermediate file, temporaryfinal.txt?)

Thursday 1 November 2012

HP Machines and Windows 8

I’ve had a bad 24 hours.  I’ve been trying to get started developing for Windows Phone 8, and as a result of the new outlandish hardware requirements to do so have had to purchase a new PC.

So, I wandered down to Curry’s and picked up an  HPPavilion g6-2241sa 15.6 Laptop – Blue for £350.  I then had to get the windows pro pack to enable Hyper-V, (which I still haven’t, at the time of writing this, managed)

Alas, I’ve stumbled into the problem that Windows Update on HP machines doesn't actually work very well (if at all).  The big 190 MB update that needs to be done locks up after reboot at 13%

After nearly 12 hours talking to support, I came across this:

http://support.microsoft.com/kb/2777330

What I did was:

go to the windows update site, and download the updates manually: KB2764870, KB2761094, and 2756872 as well as delmigprov.exe

http://www.microsoft.com/en-us/download/details.aspx?id=34908

I then ran delmigprov

did the clean boot thing

copied the files to the desktop

and then went to device manager, and uninstalled all devices that might cause a problem (2x network, card reader, 2xaudio, and web cam).

I also manually stopped the audio services in case it was the IDT audio.After running the first 2 kb updates, I needed to reboot.

Alas, that meant I had to remove all of the devices again, and stop the services after they were installed.

Now my machine has finally booted back into windows!

I am now going to create another system restore point

Since then, I’ve added another 5 windows updates, but this time without disabling the devices.

And now another restore point, and finally install of pro-pack.

All of this seems to have worked, and I’m finally up and running after only 19 hours of work.

If this has saved you time, please consider purchasing some of our software at http://www.wieser-software.com/

Wednesday 31 October 2012

Updating to Windows 8

Updating ought to have been easy, but I found it incredibly frustrating.

First, I went to the upgrade site, but after getting all the way through the purchase process, it stated that the upgrade wasn’t for commercial use.

OK.  Off to Curry’s to reserve a DVD which also prevents me having to download the whole thing: Get Windows 8 upgrade on DVD from Currys at £49.99 and apparently doesn’t have the commercial restriction, a premium of £25.00.

When I got there I started looking at a new laptop as well, but that’s another story.

So, I’m now installing from the DVD I purchased.

The first thing I need to do is uninstall the incompatible apps (some Dell stuff, an Intel USB3 driver?, and Security Essentials!?) followed by a reboot.

I chose to keep my existing, files, programs and settings.

After quite a long delay, my machine installed devices, then spent quite awhile longer preparing. 

Another reboot, and “Moving your settings” was the next task.

Following that, a personalize choice, followed by connecting to the network via wireless (I’ll do that later).  I then chose express settings, and entered my previous admin password, and chose sign in without a Microsoft account.  After “Finalising your settings” a disconcerting black screen before “Hi” Finally appeared along with the W8 intro stuff.

It eventually booted into W8, so after the initial confusion about licensing, not too bad.

Installing the Windows Phone 8 SDK was a different matter though.  At this moment, still not done, so although I have Windows 8 Pro, it doesn’t do what it needs to.

Wednesday 17 October 2012

Windows 8 Selected Item Styles in a GridView control

While building our latest app, Travel Advisories I noticed that our selected items didn’t look a lot like the selected items elsewhere on Modern UI Style Apps.

My app was generating selections that looked like this:

transparent

The selection box has the tick, but it isn’t an outline, and it’s completely filled with the color.

Eventually, I worked out that this was caused by my xaml for the ItemTemplate

<GridView.ItemTemplate>
<DataTemplate>
<Grid Width="400" Margin="3" HorizontalAlignment="Left" >
<TextBlock Margin ="20,0,0,0" FontSize="32"
HorizontalAlignment="Left" VerticalAlignment="Top"
Text="{Binding Country}" />
</Grid>
</DataTemplate>
</GridView.ItemTemplate>


You’ll note that we don’t set any background and leave it transparent.  Having looked at some sample code, I found that most of the samples were setting a background color for the ItemTemplates, so changing the background of the grid to Black makes it look like this:


opaque


Now you can see that we have a completely black background, and the corner marked with the tick, much like the other samples.  But that still isn’t the look I was after.  What I wanted was a totally transparent background showing the background behind the text.


To accomplish that requires delving into the default ItemContainerStyle and a trip into blend to do it, so do the following



  • Open the project in blend

  • Right Click on your GridView in the Objects Window

  • Expand Edit Additional Templates

  • Expand Edit Generated Item Container

  • Select Edit a copy, and edit the 290 additional lines of code

The one line of code your looking for looks like this


<Rectangle x:Name="SelectionBackground" Fill="Transparent" Margin="4" Opacity="0"/>


Where the Fill is set to a StaticResource Binding.


Having made that change, we now get the desired result:


semitransparent

Using the Snipping tool on Metro Style Apps on Windows 8

I was just about to start another blog post, and realized I had no idea how to get a snapshot of a portion of a metro Modern UI Style App screen.

The snipping tool works great, but there isn’t any way to actually see the metro app at the same time, (or so I thought, until I discovered the secret).

First start the snipping tool, by pressing the windows key, and typing snipping.

snipping

Next start your Microsoft Store App you want a snapshot of.

Now, the magic.  Press Control+Print Screen and the Snipping tool pops back on top

startsnipping

Finally, drag out your snipping area, just like you would on a desktop app and save the results.

Wednesday 12 September 2012

On Windows 8 things aren’t always what they seem

I’ve been busy the last couple of months getting started on Windows 8.

Yesterday, I was trying to get data into a WriteableBitmap, and was a bit confused by what you could actually do with an IBuffer.  The interface only contains two methods, neither of which hands off the contents of the buffer.

Charles Petzold has an article that describes his attempts to get access to the buffer, and shows that C++ code isn’t all that much faster than the C# method of writing to a stream.  After reading his blog post, I discovered that I should have added a using statement to the top of my code to get the extension methods.

using System.Runtime.InteropServices.WindowsRuntime;


Once that’s been done, you discover that there are actually quite a few extension methods that work on IBuffer, and a promising one was


public static void CopyTo(this byte[] source, int sourceIndex, 
IBuffer destination, uint destinationIndex, int count);



I’ve been there, done that and got the t-shirt.  Don’t use this function for random access into the IBuffer.  I wrote the following loop:


bmp = new WriteableBitmap(240,240);
int e = bmp.PixelHeight * bmp.PixelWidth * 4;
byte [] twopixels = new byte[8];

int startCount = System.Environment.TickCount;
buf = bmp.PixelBuffer;

for (int j=0;j<100;j++)
// now run the loop 100 times.
for (int k=0;k<e;k+=8)
{
twopixels.CopyTo(0, buf, k, 8);
}
Debug.WriteLine(string.Format("{0} ticks elapsed", System.Environment.TickCount - startCount));


To my surprise, that code was ten times slower than this code:


byte [] colors = new byte[8];
bmp = new WriteableBitmap(240,240);
int e = bmp.PixelHeight * bmp.PixelWidth * 4;
byte [] Pixels = new byte[bmp.PixelHeight*bmp.PixelWidth*4];

int startCount = System.Environment.TickCount;
buf = bmp.PixelBuffer;

for (int j=0;j<100;j++)
// now run the loop 100 times.
for (int k=0;k<e;k+=8)
{
System.Buffer.BlockCopy(colors, 0, Pixels, k, 8);
}

using (Stream pixelStream = buf.AsStream())
{
await pixelStream.WriteAsync(Pixels, 0, Pixels.Length);
}
Debug.WriteLine(string.Format("{0} ticks elapsed", System.Environment.TickCount - startCount));


So, for whatever reason, byte.CopyTo is extremely inefficient.  Looking at the code, it appears that there is a lot of checking happening to the parameters, and also a call to Marshal.Copy deep inside the checks.


ADDENDUM


Having posted this I decided to go back and modify the slow version.


For reference, to run the code above 100 times took 4633 ticks for the first method, and 312 ticks for the second.


So, to try one last time, I did this:


bmp = new WriteableBitmap(240,240);
int e = bmp.PixelHeight * bmp.PixelWidth * 4;
byte [] twopixels = new byte[8];
int startCount = System.Environment.TickCount;
buf = bmp.PixelBuffer;
byte[] Pixels = buf.ToArray();
for (int j=0;j<100;j++)
// now run the loop 100 times.
for (int k=0;k<e;k+=8)
{
System.Buffer.BLockCopy(twopixels, 0, Pixels, k, 8);
}
Pixels.CopyTo(0,buf, 0, Pixels.Length)
Debug.WriteLine(string.Format("{0} ticks elapsed", System.Environment.TickCount - startCount));


To my surprise, this was the fastest of all of them taking only 234 ticks, an improvement of 33%!

Friday 24 August 2012

Need a WrapPanel in WinRT?

I did, as the existing WrapGrid and VirtualizingWrapGrid weren’t up to the job of the panel I had used in my Windows Phone project.

I thought that because it’s a Panel implementation, it probably doesn’t have all the much code, having seen the one in Adam Nathan’s WPF 4 book.

So, I started by getting the implementation from the silverlight toolkit.

I only needed the following files:

NumericExtensions.cs, OrientedSize.cs and WrapPanel.cs.

While compiling a few namespaces were required to be changed and a couple of attributes removed, but after that, it’s now fully functional.

A new pattern for Win8 ApplicationViewState handling

While trying to port our app Bridge Stenographer I was faced with the problem of supporting the new ViewStates in Windows 8.

I didn’t really like the idea of having a bunch of duplicate controls on my UI that I hid.

I didn’t really like the idea of having a frame that I navigated to a completely separate set of controls.

And I really didn’t like the messy syntax for managing view states with the VisualStateManager, particularly in light of my previous experiences of Visual States never doing what you expect.

So here’s my idea:

First, in the Common folder, modify LayoutAwarePage.cs to make the ObservableDictionary available to the rest of the classes by making it public (or protected).

Set up bindings in your DefaultView model, labelled with keys that define the states you require.  So for instance, I need to move some items from one grid location to another based on my state changes.

DefaultViewModel["keyboardRow"] = 2;
DefaultViewModel["keyboardColumn"] = 1;
DefaultViewModel["keyboardMaxWdith"] = 465;
_fullpage = DefaultViewModel;



Where _fullpage is defined as (sorry about Wdith typo above.  How to edit in LiveWriter???)


private IObservableMap<string, object> _fullpage;
private IObservableMap<string, object> _snapped;



Then in my constructor I also add the _snapped object:


_snapped = new ObservableDictionary<string, object>;
_snapped["keyboardMaxWidth"] = 300;
// etc...


Then in my code, I simply bind to

<somecontrol MaxWidth="{Binding DefaultViewModel[keyboardMaxWidth]}" />


And swap the DefaultViewModel in response to the SizeChanged event on the page:


void BiddingPage_SizeChanged(object sender, SizeChangedEventArgs e)
{
switch (ApplicationView.Value)
{
case ApplicationViewState.Snapped:
DefaultViewModel = _snapped;
break;
default:
DefaultViewModel = _fullpage;
break;
}
InvalidateArrange();
}


Hey Presto!  New layout.
I was looking for a way to do this declaratively in the XAML, by creating the Observable collections there, but alas, haven’t yet figured out how to do that.

Problems subclassing UserControl on WinRT

While trying to figure out how to add a generic mechanism for accelerators on buttons on my Win8 port of Bridge Stenographer I was faced with blank stares when asking about Keyboard Shortcuts

AutomationProperties.AccessKey="Number2" looked like the perfect property to add on my 2 button for instance, but I was disappointed to find out that nothing supported it.

In the end, I needed to have a base class that did some of the handling for my keyboard mapping to the access keys, as I don’t want to write that code over and over again (actually, I don’t want to debug and keep parallel copies up to date, but I digress).

So, what better way than a base class I thought.

So, here’s what I did.  I had my keyboard like control based on a UserControl.  Why not just change the base class to SpecializedUserControl like this:

public class SpecializedUserControl : UserControl
{

public SpecializedUserControl()
{
}

public void ExtraFunctionality()
{
}
}



Then, I can create a new user control, and base it on this new base class like this:


public sealed partial class MySpecializedUserControlInstance : SpecializedUserControl
{
public MySpecializedUserControlInstance()
{
this.InitializeComponent();
}
}


and declare it in XAML like this:

<local:SpecializedUserControl
x:Class="hoverbug.MySpecializedUserControlInstance"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:repro"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
d:DesignHeight="300"
d:DesignWidth="400">

<Grid>
<Button>Sorry Charlie!</Button>
</Grid>
</local:SpecializedUserControl>


Interestingly, while writing this, I was disappointed to find that everything worked fine, and I wasn’t getting the error I got in my actual code.


Here’s how I instantiated the control on my page:


<local:MySpecializedUserControlInstance DataContext={Binding }" />


Not to be beaten (as it really didn’t appear to work in my code), I started porting across bits of my implementation, a feature of which was that I needed a property to attach to controls in my implementation that could hold a function to call when the AccessKey was pressed, so I did it like this in SpecializedUserControl:


public RoutedEventHandler KeyboardAction
{
get { return (RoutedEventHandler)GetValue(KeyboardActionProperty); }
set { SetValue(KeyboardActionProperty, value); }
}

// Using a DependencyProperty as the backing store for KeyboardAction. This enables animation, styling, binding, etc...
public static readonly DependencyProperty KeyboardActionProperty =
DependencyProperty.RegisterAttached("KeyboardAction", typeof(RoutedEventHandler), typeof(SpecializedUserControl),
new PropertyMetadata(null));


Now when I run the same program, I get this error:


oops


Anyone have any idea why adding a declaration of an attached property breaks it in this way?

PointerOver visual state on WinRT, it’s over even if it’s not.

I’ve been trying to get my Bridge Stenographer App ported to Windows 8 and in the process have come across a few problems.  The latest being that I click on a button on the welcome page to get somewhere else in the app, and when I navigate back, my button is still in the pointer over state, despite the pointer being elsewhere.

I’ve tracked this down to using  NavigationCacheMode="Required" on the page, in order to keep my page alive.

As a result, when I navigate back to the page, the controls don’t get whatever the equivalent of MouseLeave is, and therefore don’t transition out of the PointerOver state, and this doesn’t just apply to Buttons.  Combo boxes have this behavior as well.

You’ve been warned.

Friday 27 July 2012

Data-Binding Pitfalls on WPF, WP7, Silverlight and WinRT Part 2

Most of my data binding worries stem from implementing my view model for MVVM.

One of the things I noticed was that it was very difficult to get things right when multiple properties are combined to form another property, so a change to any input would need to raise notifications that the derived property had changed. 

This led to code that was difficult to debug, write and maintain.  In addition we found that in many cases, properties weren’t changed in isolation.  Changing one property on an object often meant others would soon change too.

So, to deal with this issue, we built a class that coalesced property notifications, and also had a representation of dependent properties which would fire when an input changed.  With the addition of a FreezeNotifications and UnfreezeNotifications mechanism, we could queue up all of the changes, and then fire each change only once.

However, we still end up with many properties on the same object potentially firing, and still requiring recalculation of layout multiple times.

In the previous post we were concerned with how data binding worked on a control, and in a control the properties are generally a Dependency Property.  In this example the properties in question simply implement INotifyPropertyChanged, and the objects in question aren’t based on the Control class, so calling Invalidate won’t suffice to defer our work.

In the end, here’s what we did. 

We had several objects that needed to connect to the data to get property notifications.  When a property changed, we marked our object as dirty in such a way we could determine what needed to be updated.

We then fired off a Task, which collected the data from the database, and built up the information required.  In the case where a previous task was already running, we called Cancel on the existing task, and then started a new task to load the newly loaded data.

This worked ok.  The tasks ran on another thread on the multi core machine, but we found that we were cancelling the task about 6 times before finally allowing it to run to completion.

How can I Stop Wasting Cycles?

We thought there had to be a better way.  And that turned out to be our old friend Dispather.BeginInvoke.  Instead of launching the recalculation immediately, we asked for it to happen when we finally got around to processing messages again.

Initially we passed it with the DispatcherPriority.DataBind, to get it into the DataBinding queue.  That indeed worked, and we no longer get any cancellation requests, as change detection all works on the UI thread, and when we finally relinquish control, we then start our task, and mark the object as not dirty.

When subsequent notifications arrive, the work is already done, so no further action is taken.  There’s probably a further improvement to be had by checking that we haven’t already marked the object as dirty, and avoiding queuing the call altogether.

Finally, we wondered if we really needed to drop to that priority level, and the answer was no; Normal priority works just fine.

The Moral of the Story?

Don’t be in a big hurry to do the work, as someone might change their mind, and you’ll just have to start all over again.  Instead, schedule the work to be done using Dispatcher.BeginInvoke. 

But BeginInvoke doesn’t exist on WINRT

It appears that CoreDispatcher.RunAsync gives us 3 priority levels, so changing to this method on WinRT will probably continue to work (if you can manage to get your hands on a CoreDispatcher object in the first place)

Thursday 26 July 2012

Data-Binding Pitfalls on WPF, WP7, Silverlight and WinRT Part 1

I've been doing a lot of work on all four platforms (WPF, WP7, Silverlight and WinRT), and am puzzled by how data-binding is supposed to be implemented.

For example, in David Anson's Data Visualization toolkit, you can be penalized with an extraordinarily long delay if property changes happen in the wrong order.
http://forums.silverlight.net/t/101287.aspx/1

The problem in that specific instance is that the control sets the default range to 1 year, but the order of changing properties can cause the problem to occur at any point.  For example, if you were to change a date time axis from a range of 1 day to 1 year and back, with intervals of 1 hour and 1 month respectively, on the way to 1 year, you'd need to set the interval first, and the range second.  In the other direction, it's the opposite.

Now with Data Binding, it's not clear how you'd arrange this.  In my case in WPF everything appeared to be working just fine, until I newed up a control for printing.  Printing worked fine, but PrintPreview had a hugely long delay, before the preview window appeared.  The culprit?  The DateTimeAxis.

It turned out the problem was provoked by my code behind setting the Interval and Interval type.  When I changed it to data-binding, the problem disappeared.

Now, I suspect the reason this fixed the problem has to do with the options on Dispatcher.BeginInvoke and the Dispatcher itself.  If you look there (in WPF) the DispatcherPriorities includes Render and DataBind levels in addition to Normal.  Shawn Wildermuth wrote an article a long time ago about the dispatcher http://msdn.microsoft.com/en-us/magazine/cc163328.aspx that provides some insights.

If you examine the code in the DateTimeAxis, you’ll see that on a property change, most of what happens is a simple call to Invalidate().  That pushes the refresh down to the Render level, allowing all of the other Invalidate calls to occur before doing any work for changes resulting from property changes.  I’ll come back to that scheduling trick in a part 2 tomorrow.

Now, my code didn’t use data binding for all of it’s properties.  It all ran on the UI thread in response to the user asking to print.  As a result, (if my analysis is correct) the initial data binding has not yet run, as we haven’t ceded control to the dispatcher.

Eventually, my UI control is asked to Measure and Arrange from my code on the UI thread, and finally UpdateLayout is called by my code.  Because I had set some of the properties in code (the Interval, and Interval Types) but not the Max and Min, when the control is being laid out it does all the work to create the stupid number of ticks for each hour in a year.

Then, inside UIElement.UpdateLayout() I have this call stack:

PresentationFramework.dll!MS.Internal.Data.DataBindEngine.Task.Run(bool lastChance) + 0x31 bytes   
PresentationFramework.dll!MS.Internal.Data.DataBindEngine.Run(object arg) + 0xb6 bytes   
PresentationFramework.dll!MS.Internal.Data.DataBindEngine.OnLayoutUpdated(object sender, System.EventArgs e) + 0x1e bytes   
PresentationCore.dll!System.Windows.ContextLayoutManager.fireLayoutUpdateEvent() + 0x154 bytes   
PresentationCore.dll!System.Windows.ContextLayoutManager.UpdateLayout() + 0x926 bytes   
PresentationCore.dll!System.Windows.UIElement.UpdateLayout() + 0x16 bytes   

So, it finally data-binds the rest of my values, and lays out the axis correctly with the intended values for Max and Min.

By switching everything to use data-binding instead mixing it with code-behind, the default values in the DateTimeControl work correctly (though the work is still wasted), and then the data-binding sets them to the new values.

It’s this wasted effort that concerns me, so future instalments will examine what can be done about it.

Wednesday 25 July 2012

Landscape Printing and Preview in WPF: It’s the overload, stupid!

We’re just finishing up a new release for our weather station software, and thought it might be nice to add printing for our users.

The printouts lend themselves to Landscape orientation, but much as we searched, we couldn’t find a way to get the DocumentViewer control to show us the preview in Landscape mode.

In the end, there are a sequence of things that need to be done.

First, when you create your PrintDialog, make sure you set the PageOrientation property to PageOrientation.Landscape.  That in itself isn’t enough though.

So, now store the size of the paper from the successful print dialog, and construct your DocumentPaginator object.

var ms = printDialog.PrintTicket.PageMediaSize;
Size pageSize = (printDialog.PrintTicket.PageOrientation == PageOrientation.Portrait) ?
new Size(ms.Width.Value, ms.Height.Value) :
new Size(ms.Height.Value, ms.Width.Value);

var Paginator = new SamplePaginator(uc, pageSize);


Where uc some control or Framework Element.


And here’s the important bit.  When you return a DocumentPage, make sure you use the overload that takes the PageSize you calculated above.  If you do, then preview works great. 


I had naively assumed that overriding the PageSize abstract property would do this job, but it did not.

Sunday 22 July 2012

Win8 WebView not ready for Prime Time

Yesterday (July 21, 2012) I spent the day at a Windows 8 DevCamp, and had a lot of support from Microsoft starting to get our Travel Advisories App ported to Windows 8.

The app renders html using the WebView control, but in trying to port it, I ran into a number of problems.

The first problem I encountered was that there is no equivalent of the OnNavigating event, raised by the WP7 control.  In WP7, what we did was perform a WebBrowserTask.Show() on containing whatever page was being navigated to.

Launching the web browser wasn’t that great of an experience on Win 8 in any case, so I decided I’d put that on hold.  That’s when the second problem appeared.

We construct the first page shown in the app in memory, and then use NavigateToString.  Unfortunately, the page doesn’t appear to accept clicks or navigate reliably when you first navigate.  Resizing the app on Win8 appears to make the WebView finally show it’s scroll bars, and take navigation hits.  On that note, I took the train back to Cambridge.

This morning I had a few more ideas.  I thought, that since I can’t pop open a new web browser on navigate, I’d try to handle the navigation to a new page in the app.  I do this by using the LoadCompleted event.

Unfortunately, this event isn’t reliably raised on a new page, nor is the NavigationFailed event.

My plan was to keep a count of the number of times navigation occurred (assuming that none of the pages raise back by themselves), and then allow navigation back by executing a javascript expression “window.history.back();” depending on how many pages I’d navigated.

Unfortunately, while this occasionally works, it also occasionally throws an exception.

So, all in all, I think the message in all this is: If your app needs an HTML viewer, your in for a world of pain.  I don’t know if this will be resolved before Win8 ships, as apparently it’s RTM in just 8 days.

Caveat Coder!

Saturday 14 July 2012

WP7 ScheduledActionService = Scheduled Crash!

I’ve been on the trail of an irreproducible bug for a couple of weeks now, described on the forums

In effect, what has been happening is that ScheduledActionService.Find is throwing an exception, but I wasn’t able to duplicate the fault in our program Terminator which shows sunrise and sunset times.

However, we’ve been trying to get rid of some other navigation bugs, and it struck me that this was probably another banging on the back key bug.

And it turned out I was right, that’s exactly what it was.  If you repeatedly stop and start our app (and probably any other app that refreshes a live tile on startup) you can provoke this failure.

It appears the crux of the problem is that the previous instance of the app has not quite completed when you launch the new instance.  If you get the timing exactly right, the call to ScheduledActionService.Find will throw, and if you're even more lucky you’ll catch it in the debugger, and see that immediately after it fails, it throws a ThreadAbortException

That’s a pretty good clue that there’s some internal bug that is triggered by the previous instance not having let go.

My solution?  Initially I thought wrapping a mutex around the whole program would do it, but it still failed.  That implies that the abort on the previous version released the mutex, but hadn’t yet cleaned up the remainder of the ScheduledActionService.

So the working solution is to retry the call to ScheduledActionService.Find up to three times, delaying 100ms each time, to let the previous instance shut down correctly and get out of the way.  Timing of course may vary depending on your app.

Wednesday 11 July 2012

Windows 8 CP acmFormatChoose Bug

Yesterday, I decided to take the plunge and install W8 CP on a VHD, as described by Ed Bott here

It took a good few tries, but the step I hadn’t counted on was when I created the VHD, it takes a very long time to complete, and the UI doesn’t show you much in the Disk Manager.

Eventually, the 64 bit version was all up and running, so I decided to try our program RIP Vinyl, and was pleasingly surprised that our custom built installer wrapper we use for all of our projects installed without a hitch.

So, I launched the program, and recorded a test stream from YouTube.  It worked straight away on Windows 8!

Unfortunately, when I went to change the recording format to MP3, I started to hit problems.  Pressing the format change buttons did nothing.

The code allows the user to change the recording format by selecting a format via the acmFormatChoose dialog, but unfortunately, no matter what I tried, I keep getting a return code of 0x0000000B, or MMSYSERR_INVALPARAM

I’ve now built a very simple test using VS2010 and an MFC dialog based app, which runs fine on everything but W8.

I haven’t yet tried on the 32 bit version of W8.

Here’s the code I run on a button press in my MFC app:

MMRESULT Cacmformatchoosetest10Dlg::CheckFormat()
{
ACMFORMATCHOOSE acmfmtch;
int waveFormatExSizeMax;
TCHAR waveformatName[_MAX_PATH];
waveformatName[0] = 0;


acmMetrics(NULL, ACM_METRIC_MAX_SIZE_FORMAT, &waveFormatExSizeMax);

void *buffer = _alloca(2 * waveFormatExSizeMax);
WAVEFORMATEX &wfx = *( (WAVEFORMATEX *) buffer);

memset(&wfx, 0, sizeof(wfx));
wfx.cbSize = 0;
wfx.nChannels = 2;
wfx.nBlockAlign=4;
wfx.nSamplesPerSec=44100;
wfx.wBitsPerSample=16;
wfx.wFormatTag = WAVE_FORMAT_PCM;
wfx.nAvgBytesPerSec=44100*4;

ZeroMemory(&acmfmtch, sizeof(acmfmtch));

acmfmtch.cbStruct = sizeof(acmfmtch);
acmfmtch.fdwStyle = 0;
acmfmtch.pfnHook = NULL;
acmfmtch.pszName = waveformatName;
acmfmtch.cchName = _MAX_PATH;
acmfmtch.pszTitle = _T("Title");
acmfmtch.hwndOwner = NULL;
acmfmtch.pwfx = &wfx;
acmfmtch.cbwfx = waveFormatExSizeMax;

acmfmtch.fdwEnum = ACM_FORMATENUMF_INPUT ;
acmfmtch.pwfxEnum = NULL;

return acmFormatChoose(&acmfmtch);
}


If anyone wants the entire project to try, please contact me via @WieserSoftware on twitter.

Friday 6 July 2012

Yes, the Windows Phone Marketplace is still broken.

Some of you may have noticed me complaining on Twitter that my apps are not appearing in various marketplaces around the world.

I’ve been testing this by going to the marketplace, and searching for our publisher name (wieser) and then changing the country listed from the home country that appears to various others.

Oren Nachman (who did a great talk over here in London at a Dev Days a few years back) suggested I raise a ticket so I did.  Here’s the question:

I've noticed that some of my apps are still not visible in some of the marketplaces they should be a month after certification. What's gone wrong? Missing apps include some or all of: Skied Demon and Bridge Stenographer, Travel Advisories in the following marketplaces (at least) en-AU, en-NZ, en-SG de-DE, de-CH, de-AT, es-MX, es-ES Who knows how many more. I don't have the full list of marketplaces... Can you please advise?

To the Marketplace team’s credit, I got a response in less than a day this time, though the news isn’t good.

Thank you for contacting Windows Phone App Hub Developer Support. There is a known issue affecting some developers in markets outside of the US, where apps are not searchable by app title or keywords in some country's marketplaces, and only accessible via the deep link. Our engineers are aware of this top priority issue and are actively working to resolve it, as we understand that visibility is one of the most important aspects to app popularity. The ETR is currently next week provided by the engineering team.

We apologize for the inconvenience, and appreciate your patience while we resolve this matter, and work to improve the experience of the App Hub and the Windows Phone Marketplace.

The good news is, my apps will be discoverable, and I’ll finally be able to pay the rent from sales of my apps.  Or not.

In any case, now you know.

Wednesday 4 July 2012

I really do hate hardware


Today one of my customers was trying to print with a Kodak ESP C310 printer and our program (http://www.wieser-software.com/payslips) crashed when calling a WPF 4.0 program's Print Dialog.

We installed the latest drivers, but the problem remained.


As a last ditch effort I selected "print directly to printer" on the preferences for the printer, and it worked, so it appears there's some incompatibility with the Kodak print spooler.

Thursday 28 June 2012

Burnt by a faulty WPF install

Over the past couple of days, we’ve been trying to debug a problem reported by a customer of our WPF program, Payslips for PAYE Tools.

The customer was reporting that the program was crashing, and not generating any error reports (internally, we hook into the unhandled exception handler, and generate an email message containing the report, so we can examine the flaw).

Eventually after connecting to his machine remotely, we discovered that there were events in the event log, and they were TypeInitializationExceptions.

That exception is thrown when a static constructor fails for some reason.

Unfortunately, that implied that some of our static members were failing to initialize correctly.  So, we took the initialization and moved it into the instance constructor (as it was the App class), hooked up the error handler at the beginning of the class constructor, and crossed my fingers that it would catch the error.

But it didn’t work!  So I added a message box at the beginning of the class constructor.  That didn’t show either on the afflicted system.  With hundreds of working installs, it had to be something to do with the installation, so another connection to the remote PC was made, and we noticed that there were outstanding Windows updates for .NET 4.0

We left the customer to install them, but he told us that the updates also failed.

Eventually, he told us that the error messages led him to the .NET removal tool (link to follow).

We suggested that he should run that, reinstall our program, and let it download the .NET framework.

And what a surprise, our program now works correctly.

But what a horrible experience for the end user!  How does an install get into that state, and how can we diagnose it?

Tuesday 12 June 2012

WPF window rendering woes

Today, I started adding some functionality to a new WPF app, and noticed that as I resized my window to be larger, there were black strips appearing on the bottom and right sides of the client area, that were eventually filled with the controls on the page.

This looked horrible, and it appears I’m not the first one to run across this, however, there still seems to be no resolution.

As I’m an old school MFC/C++ guy, I figured there had to be a way to do this.

My first strategy was to hook in a new WndProc handler, and process WM_ERASEBKGND messages.  I thought, claiming I’d erased it would do the job, but that made no difference.

So, I actually implemented code to fill the clip region with the WINDOW_COLOR brush, and that did fix the problem.  No more black edges, but that was all a little bit unsatisfactory.  What I really wanted to do was register my own class for the WPF window, and set the background brush correctly to match the window.

That doesn’t appear to be possible, but it is possible to PInvoke and call SetClassLong on the background brush.

So my preferred solution is set the class background brush, and watch WPF draw it correctly. It appears that WPF creates a new class for each application so this should be safe, though if it’s not the previously described solution would definitely work.

Back to the Desktop and WPF, no WinRT for me

I’ve been working pretty much full time lately on Windows Phone 7 apps, and making pretty much no money.  As I have a house and a family, this isn’t a situation that can continue for very much longer.  One of our previous WPF apps is doing quite well on the desktop, and makes more in a single sale than I make in a month of Windows Phone App sales and ad revenue.

I have considered porting some of my apps to WinRT for Windows 8, but based on what Josh Smith says here http://joshsmithonwpf.wordpress.com/2012/03/20/does-anyone-actually-care-about-winrt/ I think my gut feel that it is a lot of work, and it will probably come with more pain than gain for me is probably spot on.

I was one of first into WP7 development, and the theory was that we’d be discoverable and get early sales.  What happened instead is that others got in on the bandwagon, and produced similar apps, so in my view, there’s no benefit to showing my hand early. 

If it really is that good of an environment, it shouldn’t be that hard to port the apps to the new platform.

Saturday 26 May 2012

The EU Cookie directive is impossible to implement

Well, OK, maybe not impossible, but it might as well be.

Here’s why.  If you include any content that’s not directly generated on your site, an http request to set a cookie from the third party site appears to be honoured by your browser.

For instance, I set up a file on my server that runs the following php on request for a particular javascript file:

<?php
header("Content-type: text/javascript");
header("Set-Cookie: GOTCHA=value; path=/; expires=Mon, 28-May-2012 00:00:00 GMT");

echo <<<EOT
alert('hello')
EOT

?>



If I then go to a third party site, like jsfiddle.net and include the javascript file from my server and run it, it turns out that a cookie is indeed set for the third party domain (my site containing the javascript).


Now, in theory the law requires the third party site to request permission before dropping the cookie, however, many third party affiliate networks are requiring the affiliate to request the permission.


Note that the Information Commissioner itself is vulnerable to this, because despite asking for permission, they include a script from another website.  In this case it’s: http://ajax.googleapis.com/ajax/libs/jquery/1.5.1/jquery.min.js


So as a result, they could unknowingly cause cookies to be deposited on your computer.

Sunday 20 May 2012

More bugs in the Toolkit ListPicker

We recently updated our Chromatic Tuner app, Tune Up, and after the update using the latest fixes for the Silverlight Toolkit was disappointed to find some new stack traces on the control panel.

As usual it’s a navigation bug, this time caused by a storyboard completing after something else has happened, in this case, someone pressed the start button after the navigation began.

As a result, the code in PickerPage.xaml.cs calls NavigationService.GoBack(); in the OnNavigatedTo handler.

Then the storyboard completes, and NavigationService.GoBack(); is called again while navigating.  We all know this is going straight to the exception handler.

The fix and issue are at http://silverlight.codeplex.com/workitem/10769 but I’ll duplicate it here.

private void OnClosedStoryboardCompleted(object sender, EventArgs e)
{
// Close the picker page
if (NavigationService.CanGoBack)
{
// Only do this if we can go back, or we crash
// navigate to start menu before this happens provokes.
NavigationService.GoBack();
}
}



But wait, there’s more!


While trying to diagnose this problem, I was playing around with the ListPicker trying to figure out exactly what might be going on, and I found another problem.


Immediately after you make your selection, the transition begins, and effectively you’ve made your selection.


But it’s actually possible to click on another item, and select that during the transition!  I consider this undesirable behaviour too.  You made your choice, and the transition began, yet you can change it at the last minute?  BZZZZ.  Wrong.


Here’s the fix for that one, again in ListPickerPage.xaml.cs:


private void ClosePickerPage()
{
IsOpen = false;
// AAW: disable picker on exit.
Picker.IsEnabled = false;
}

Saturday 19 May 2012

Don’t use NavigationOutTransition from the Toolkit

I’ve recently updated a bunch of our software at www.wieser-software.com/m and have been noticing while demonstrating it occasionally without a data connection, that it’s possible to end up with either a blank screen or two pages shown on top of each other as a result of navigation.

I think I’ve tracked it down to a bug in the Toolkit, though I can’t work out how to fix it.

The problem arises when you are transitioning away from a page with a NavigateOutTransition, and then end up navigating back into another page (maybe the same one) before that transition has been completed.

When this happens, your program will be unhappy.

The only way I’ve found for now to fix it is remove the NavigationOutTransition elements completely from my pages.

You can follow the issue here on the Silverlight Toolkit pages:

http://silverlight.codeplex.com/workitem/8293

Sunday 13 May 2012

Formatting a Data Bound TimeSpan on WP7

Today, I was attempting to format a data bound TimeSpan for our upcoming application using the Custom TimeSpan Format Strings provided on MSDN

Much to my surprise, no matter what I tried, it didn’t appear to format the text, and I’m not the only one to find this.

TimeSpan ts = TimeSpan.FromSeconds(1.24);
string st = string.Format(@"{0:hh\:mm\:ss}", dt);
// st = "00:00:01.2400000"


Clearly the seconds formatting is not working correctly.  And worse, the documentation states that the time separators are not placeholders.


In my case, I know my TimeSpan is always less than 24 hours, so I thought the best solution was to convert it to a DateTime using a converter.


public class TimespanToDateTimeConverter : IValueConverter
{
public object Convert(object value, Type targetType,
object parameter, CultureInfo culture)
{
return new DateTime(((TimeSpan) value).Ticks);
}

public object ConvertBack(object value, Type targetType,
object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}


Now in my xaml, I do this to bind to an object named Elapsed:

 


<Grid>
<Grid.Resources>
<fwk:TimespanToDateTimeConverter x:Key="asDate" />
</Grid.Resources> ...
<TextBlock Text="{Binding Elapsed,
Converter={StaticResource asDate},
StringFormat='{0:HH\:mm\:ss\}'}"
/>

</Grid>

This neatly solves the problem, and in the process, delivers locale specific separators as well.

Friday 4 May 2012

One of our ListItems is missing! ListPicker Bug Alert!

I used the November ‘11 Silverlight Toolkit ListPicker control in one of my upcoming WP7 apps, and was surprised when impatiently, I started scrolling down while my full screen picker page was opening.

Unfortunately, when I got to the bottom of the page, some of the items were not visible, though vertical space was reserved for them.

Off to the source I went, and discovered that the ListPicker control initially sets every item on the page to be have a PlaneProjection with a RotationX of –90.  That would at least explain why my items weren’t visible.  They were rotated away from the field of view so they couldn’t be seen (Just like Calvin and Hobbes in 2D form)

So how did it happen?

Deep inside the ListPickerPage.xaml.cs file, in the UpdateVisualState function, there’s an IList<WeakReference> itemsInView that holds the list of items currently in view, then a few lines later, a Dispatcher.BeginInvoke on UpdateOutOfViewItems.

UpdateOutOfViewItems then collects the list of visible items again.  Only they might not be the same items.  In fact, any items that are new to the set will not be drawn correctly.

The Solution

The solution of course is to change the call to pass in the list of in-view items to the UpdateOutOfViewItems, changing the call to

Dispatcher.BeginInvoke(new Action(() => UpdateOutOfViewItems(itemsInView)));

and the signature to:

private void UpdateOutOfViewItems(IList<WeakReference> itemsInView)

and finally we don’t call GetItemsInViewPort in the UpdateOutOfViewItems.

I’ve added this fix as a hotfix to the SilverlightToolkit project here:

ListPickerPage.xaml.cs

Tuesday 1 May 2012

CryptAcquireContext fails again

Today I spent about two hours with a customer who was having problems installing some of our full version software.

When he ran the installation program, he was presented with a series of error messages, the first one being:

Error during CryptAcquireContext along with error code 0000054F or 1359

That error code translates to ERROR_INTERNAL_ERROR.

After some psychic debugging, I realized it probably had something to do with his user account and the way his machine had been configured by the manufacturer.

The default account settings some manufacturers use

I’m not exactly sure what was going on, but as I asked him what antivirus software he runs and the answer was none, it suddenly occurred to me that he probably only had only one user account on the machine, and that user account had no password.  Both of those guesses proved correct.

And sure enough, the problem was solved by doing the following:

  • Create a new administrator account on the machine
  • Create a password for the new administrator account
  • Log into that new account
  • Install the software

Tuesday 24 April 2012

Silverlight Toolkit ListPicker changes

After my post about a week ago, about the Silverlight Toolkit November 2011 installer installing the wrong version I took some advice and started using NuGet.

So, as I’ve been updating my apps, I’ve begun adding the references to the latest toolkit.  Today, I came across a breaking change (I’ve switched from Version 1.0 to Version 7.0 of the toolkit in one jump) in the ListPicker.

My first clue should have been that ItemCountThreshold="3" raised an error, so I removed it, as the new threshold is consistent with my application.

Then I noticed that my picker page seemed to have a different font from the version of our Chromatic Tuner for Windows Phone: Tune Up that’s released on Marketplace.

It turns out, the ListPicker now navigates to a new page, which raised another bug in our software, because previously OnNavigatedTo was not called after the Picker was dismissed. 

As the program was so simple, we set the selected Item in the ListPicker irrespective of whether we were a new page, and therefore lost the new selection.

Wednesday 18 April 2012

Silverlight Toolkit Nov 2011 installer borked

If like me, you’re using the Silverlight Toolkit, and installed the November 2011 installer and are shipping, there’s a problem you probably want to know about.  You may have suspected something was wrong, in that it actually installed into an October or August folder originally.  Read on…

My stack trace matched the one reported here: http://silverlight.codeplex.com/workitem/10220

I was getting crashes in Context menu, and decompiled the Toolkit.dll I was shipping, and was surprised to find that some null checks were missing in the decompile compared to the source code that was shipped in the same install.


As a result, I downloaded the 71382 source, and rebuilt, and found the decompile now matches.


My conclusion: The dll's installed with that build are faulty. I’ve uploaded my build here

http://silverlight.codeplex.com/workitem/9982

Don’t think removing and adding a reference is all you need to do either

I tried that, and the old Microsoft.Phone.Controls.Toolkit.dll was still the one built into my xap file, and it kept pointing to the old one in the original folder, despite adding a reference to the new file.

In the end, I needed to manually delete the dll from the bin/Release and bin/Debug folders.

Addendum 19/April/2012

@windcape (Claus Jørgensen) suggested I learn to use NuGet, and he’s right.  Nuget does deliver a more up to date package.  Get the toolkit here:

http://nuget.org/packages/SilverlightToolkitWP