views:

35

answers:

1

I have a bit of a chicken-and-egg problem here...

I want to print map data that is retrieved asynchronously from a web service. The problem is I don't know the selected paper size (which affects the size of the map I need to request from the service) until the user presses OK on the print dialog and the PrintPage event is fired.

The only thing I can think of is to somehow "pause" the entire printing process in the middle of the PrintPage event, retrieve the map image, set the current page's PageVisual to the map image, and then let the printing process continue. But this does not seem either possible or "correct".

I thought of having the user select a page size from a combo box before printing (that way I could retrieve the proper image size and enable the "print" button only after all the map data is retrieved). But then the user would need to select the page size twice, once from my combo box and once from the print dialog. If they selected 11x17 from the combo box and then just banged OK on the print dialog (which is very likely), it would print an 11x17 layout to the default 8.5x11 paper size.

The only other mention of this problem I found is http://betaforums.silverlight.net/forums/p/192371/444897.aspx, and they didn't find a solution either.

+1  A: 

There is no direct solution to this problem. The print engine is in charge here and demands a visual for the next page. A better model from the developers point of view would have been to invert the events into methods and have the code call PrintPage. I'm sure there are intractable technical reasons why that couldn't have been done.

As I see it you have two choices. One is to simply block the thread with a WaitHandle in the PrintPage event while you wait for the asynchronous operation to complete. I can't believe I'm saying that but in this case its reasonable viable. Something like:-

 using(var waitHandle = new AutoResetEvent(false))
 {
      // Some intial code
      var result = YourAsyncOperation(parametersNeeded, () => waitHandle.set());
      bool signaled = waitHandle.WaitOne(30000);  // 30
      // Conitnue as appropriate (result might be indicate an error, signaled might be false indicating a timeout). 
 }

Your other option is to ensure you have enough data client side for Silverlight code to do the layout work itself.

AnthonyWJones
That worked! Not exactly an elegant solution like you said, but if Silverlight restricts me to printing in the UI thread and only in an event directly triggered by the end user, it will have to do. The only problem is it freezes the UI momentarily while printing (since the thread is blocked) but I can live with that.
pjabbott