Restoring Pivot Scroll on WP7 Tombstone resume
Putting the user back to the correct pivot item when they return to a tombestoned application whose last visited page contained a Pivot is pretty easy, but ensuring that they are put back to the right scroll position if they’ve scrolled down a list isn’t quite as easy.
In the code below I have a method which returns the first ScrollViewer under an item. This works well for me, but if your PivotItem’s contents contain ScrollViewers then you’ll need something more sophistacated.
In the OnNavigatedFrom I follow the standard pattern Microsoft recommends, and store away the scroll offset in the page state.
In the OnNavigatedTo I recuperate the scroll position, but cannot yet scroll because the PivotItem’s contents have not been loaded. Instead I store the scroll position, and then when the pivot has been loaded I then scroll. In my XAML I hook up each PivotItem’s Loaded event to invoke PivotItemLoaded
- static ScrollViewer FindScrollViewer(DependencyObject parent)
- {
- var childCount = VisualTreeHelper.GetChildrenCount(parent);
- for (var i = 0; i < childCount; i++)
- {
- var elt = VisualTreeHelper.GetChild(parent, i);
- if (elt is ScrollViewer) return (ScrollViewer)elt;
- var result = FindScrollViewer(elt);
- if (result != null) return result;
- }
- return null;
- }
- protected override void
- OnNavigatedFrom(System.Windows.Navigation.NavigationEventArgs e)
- {
- base.OnNavigatedFrom(e);
- State["MainPivot.SelectedIndex"] = MainPivot.SelectedIndex;
- var pivot = (PivotItem)MainPivot.SelectedItem;
- var scrollViewer = FindScrollViewer(pivot);
- State["scrollViewer.VerticalOffset"] = scrollViewer.VerticalOffset;
- _newPageInstance = false;
- State["PreservingPageState"] = true;
- }
- // Communicates scroll position between OnNavigatedTo and PivotLoaded
- private double _pivotScroll;
- protected override void
- OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e)
- {
- base.OnNavigatedTo(e);
- if (!_newPageInstance || !State.ContainsKey("PreservingPageState"))
- {
- return;
- }
- MainPivot.SelectedIndex = (int)State["MainPivot.SelectedIndex"];
- // Can't scroll now because Pivot's contents won't have been loaded
- _pivotScroll = (double)State["scrollViewer.VerticalOffset"];
- }
- // Hooked up to each pivot item's Loaded event handler.
- private void PivotLoaded(object sender, RoutedEventArgs e)
- {
- if (_pivotScroll == 0 || sender != MainPivot.SelectedItem) return;
- var pivot = (PivotItem)sender;
- var scrollViewer = FindScrollViewer(pivot);
- scrollViewer.ScrollToVerticalOffset(_pivotScroll);
- _pivotScroll = 0;
- }
Generating Silverlight / Windows Phone compatible Thrift proxies
Thrift is a software framework for scalable cross-language services development. It combines a software stack with a code generation engine to build services that work efficiently and seamlessly between C++, Java, Python, PHP, Ruby, Erlang, Perl, Haskell, C#, Cocoa, Smalltalk, and OCaml. http://thrift.apache.org/
There are two reasons for this post:
- to float some ideas for C#changes to the Thrift development community.
- to remind myself in the future what I need to do to download, modify and build the Windows Thrift compiler, and
The idea is to maintain backwards compatibility, whilst at the same time generating Silverlight (and consequently Windows Phone 7) compatible proxies.
There are two sets of changes. One to the C# code generator (t_cpp_generator.cpp), and the other to the runtime files (mainly THttpClient.cs).
Downloading and building the thrift compiler
To try out these changes on Windows, first install the latest version of Cygwin from http://cygwin.com/, then install the various packages as described here: http://wiki.apache.org/thrift/ThriftInstallationWin32
You’ll also need to install Subversion.
Next pop open the Cygwin shell, and fetch the latest source, as described here: http://thrift.apache.org/download/
Finally, build the source you downloaded, again as described here:
http://wiki.apache.org/thrift/ThriftInstallationWin32
In my environment I build using:
And then I run the new thrift compiler:
Code Generator changes
The code generator (t_cpp_generator.cpp) changes involve generating two additional methods for each “standard” method: a Begin_… method and an End_… method.
Whereas previously there might just have been a method such as this:
1: SyncState getSyncState(string authenticationToken);
Now, two additional methods get generated:
1: #if SILVERLIGHT
2: IAsyncResult Begin_getSyncState(AsyncCallback callback, object state, string authenticationToken);
3: SyncState End_getSyncState(IAsyncResult asyncResult);
4: #endif
The two methods allow for the asynchronous invocation of methods, using the standard .NET asynchronous invocation pattern.
In addition, the generated standard method (“getSyncState”) method is modified when building for Silverlight, to make use of the Begin… and End… methods:
1: public SyncState getSyncState(string authenticationToken)
2: {
3: #if !SILVERLIGHT
4: send_getSyncState(authenticationToken);
5: return recv_getSyncState();
6:
7: #else
8: var asyncResult = Begin_getSyncState(null, null, authenticationToken);
9: return End_getSyncState(asyncResult);
10:
11: #endif
12: }
As you can see, when not running Silverlight the standard code path is invoked, but when running Silverlight the asynchronous methods are invoked (the End… method blocks the current thread until the Begin… method completes). This is not something you should be doing on the UI thread.
The generated Begin… and End… methods are pretty thin:
1: public IAsyncResult Begin_getSyncState(AsyncCallback callback, object state, string authenticationToken)
2: {
3: return send_getSyncState(callback, state, authenticationToken);
4: }
5:
6: public SyncState End_getSyncState(IAsyncResult asyncResult)
7: {
8: oprot_.Transport.EndFlush(asyncResult);
9: return recv_getSyncState();
10: }
Note the call to EndFlush above – this is one of the changes made to the runtime. The other is invoked by the generated send_getSyncState method:
1: #if SILVERLIGHT
2: public IAsyncResult send_getSyncState(AsyncCallback callback, object state, string authenticationToken)
3: #else
4: public void send_getSyncState(string authenticationToken)
5: #endif
6: {
7: oprot_.WriteMessageBegin(new TMessage("getSyncState", TMessageType.Call, seqid_));
8: getSyncState_args args = new getSyncState_args();
9: args.AuthenticationToken = authenticationToken;
10: args.Write(oprot_);
11: oprot_.WriteMessageEnd();
12: #if SILVERLIGHT
13: return oprot_.Transport.BeginFlush(callback, state);
14: #else
15: oprot_.Transport.Flush();
16: #endif
17: }
The generated recv_getSyncState() has not changed.
The changes in the generated code boil down to asynchronous invocations at the transport layer (BeginFlush and EndFlush).
There are also changes to #ifdef out the Serializable attribute for generated structs, since this is not supported by Silverlight.
Runtime changes
There are minor tweaks required to THashSet, TProtocol and TBinaryProtocol because Silverlight does not support the full .NET framework API.
The main change is to TTransport.cs to introduce the BeginFlush and EndFlush methods shown above, and then to THttpClient.cs to actually implement these methods.
The existing Flush method is #ifdefed out when building using Silverlight, because it makes synchronous calls which are not supported by Silverlight.
Instead, the BeginFlush builds a request and then invokes the HttpWebRequest.BeginGetRequestStream method, passing a local GetRequestStreamCallback method as the callback.
The GetRequestStreamCallback method is invoked once the runtime has the request stream. It then writes out the data and invokes the HttpWebRequest.BeginGetResponse method, passing a local GetResponseCallback method as callback.
The GetResponseCallback notifies the original caller (in the generated code) that the request has now completed.
The EndFlush method waits for the corresponding BeginFlush method to complete, and if there was an exception thrown at any point, it raises the corresponding exception.
The changes
The changes files are here. If there is interest and these changes make sense, I’ll submit a patch.
Tilt to turn pages in Kindle Android: Nope!
I bought an HTC Desire Android mobile phone a couple of months ago.
When I first got it, there were two applications that were missing that I really really wanted: Audible and Kindle.
Both were recently released, and despite this, my life is in fact not now complete. There must be some other app for that.
I’ve been thinking about what I could develop.
As I read using the Kindle app the screen becomes smudged with my tapping the screen to change the page, and I thought it would be nice if I could change pages by tilting the phone to the right in a quick nudge.
I defied the temptation to start coding, and did some research. It looks like it isn’t possible to do what I want using the public SDK, and to save myself the pain of rediscovering why in six months, when I have forgotten, here are some notes.
For this to work I’d need three things: A background process (called a service on Android), a way for it to detect when the phone has been tilted, and a way for it to tell the Kindle App to change the page, when it is running.
Creating a background process is pretty straightforward, and there is a sensor API that can be used to detect when the phone has been tilted.
Telling Kindle to change the page isn’t so easy. I thought I’d found it when I discovered the IWindowManager.injectPointerEvent method, but I quickly found that this was not part of the documented Android API, and using it would be very very bad.
I was left with trying to find out whether the Kindle App itself had any way for other apps to tell it to change page. The standard way of doing this would be to expose an Intent which other apps could invoke.
Unfortunately by dumping the Kindle App’s manifest from its installation (APK) file, it looks as though the only intents exposed are the standard MAIN, LAUNCHER, VIEW, DEFAULT and BROWSABLE intents.
Game over, unless I’m willing to go beyond the public API, which I’m not, right now at least. Unless anyone else has any ideas?
Ploze 0.7.6 released (Windows Mobile Evernote Client)
You can now:
- Limit the synchronization size (in terms of note size, or last modification)
- Choose which notebooks to display
- Choose to download notes whose contents were not synchronized
- Sort notes by Title, Size, Last Update, Creation date
- Choose into which notebook new notes are placed
Also:
- A bug where strangely named attachments caused ploze to not synchronize has been fixed.
- Fixed bug causing large notes not to display properly
- You can now select the notebook to display on the main note list (notes from all notebooks are displayed by default)
- Added GPS support when creating a new note, which can be enabled under "Options"
I've also shared some thoughts on what might come next (think an Andoid version): http://www.ploze.com/forums/ look for "Plans and purpose for Ploze ..."
More at http://ploze.com/
Closed down MceFM
Click here to take survey to help me decide whether to create a new release of MceFM.
A couple of years ago I created a Windows Media Center addin called MceFM which let you listen to Last.fm within Media Center.
However Last.fm have changed their Application Programming Interface (API), and charge for access from Switzerland – leaving it unviable for me to continue…
Mcefm.com now redirects to this page.
Do check out BeebMC which lets you listen to BBC radio within Media Center.
Just released Ploze: An Windows Mobile Evernote client
With what I think is stunning timing, just as Microsoft announced they are taking their mobile development in a different direction with Windows Phone 7, I’ve just released a new Windows Mobile product I’ve created called Ploze, which works with an existing service called Evernote .
Evernote is a fantastic notes service, with killer features, such recognizing text in image notes, meaning that those notes are found when you search for words in the image text.
There are plenty of Evernote clients offered by Evernote , including clients for Mac, Windows, iPhone, Android, and Windows Mobile.
The official Evernote provided Windows Mobile client comes with some restrictions – it works by connecting to the online Evernote service – it doesn’t store notes locally and let you work offline.
Necessity being the mother of invention, I decided to create a client that works as I would like it to, and yesterday I released it.
Available at http://ploze.com/

The Amazon Kindle: A European perspective
Having told my wife that I definitely did not want an Amazon Kindle E-Reader for Christmas, I found myself with a substantial Amazon.com gift voucher, and decided to splurge.
The immediate result was an infuriated wife, and dark mutterings about how difficult it is to buy me presents. Almost as immediate was the arrival of the Kindle. Although shipped from the US, two days after placing the order my new Kindle arrived.
Perfidy?
There is something about the film Children of Men which captivates me: the tired depiction of a dying world set 10-15 years into the future, where no children are being born is compellingly rendered. It starts with a news report that the world’s youngest person, an 18 year old, had just died.
I decided to make the book upon which the film was based my first purchase. Written by P. D. James, it is a well written, substantial work, and it uses many words that I don’t know (perfidy, viva voce, farrago to name a few). That was where I found the first of the advantages to using the Kindle to read books: it includes a built-in dictionary. Whenever I hit a word with which I was not familiar I moved a highlight in front of the word, and up popped a dictionary definition. I suspect that I’ve ploughed through many a book in the past and simply ignored the words I didn’t know.
When reading I very quickly found that I was unaware of the fact that I was reading from an electronic device. The use of e-ink (which is a display technology that does not strain the eyes) made a big difference. I was totally engrossed in the story, and the fact that I didn’t have a book in front of me made no difference. I was in the story.
I need it now!
Buying books from Amazon when you live in Switzerland is a pain. You pay a fortune in shipping charges, and then have to wait for days for the book to arrive. This is the second advantage to the Kindle: immediate delivery of books. The Kindle has a free wireless (not wifi, but a 3G data link over the mobile telephone network). You don’t have to insert a SIM, it just works. Books you order appear within minutes on the device.
Try before you buy
As useful as the immediate delivery of books is, the third advantage is a killer, you get to download the first chapter or so of any book for free to see if you like it. This is so convenient – I read the first few pages, and if I don’t like it, I delete it, and forget about it. On the other hand if it is really good, a couple of clicks later I’m reading the whole book.
A book wherever you go
The fourth and final advantage is that you can read any of your Kindle books on your PC or iPhone too. They are there too, just like that, using free software from Amazon. So if you are in shopping queue you can pop out your iPhone and continue to read that book you were reading at home on your Kindle. And, wait for it, the pages are synchronized, so that when you go back to the Kindle it will pick up where you left off on the iPhone, and the reverse.
The downside
There are some drawbacks. Although Kindle books cost less than physical books, they cost more to buy in Europe than in the US, and the range is much smaller. Some books are not really good to read on the Kindle, such as a technical book I bought on Microsoft Project, although I find reading on the PC (while running Project to try things out) works well.
Who am I kidding?
We are still in January. So far I am really enjoying reading from the Kindle, and I am reading much more than I do normally, although that is probably because I’m keen to justify to myself that it was a sound investment.
Nevertheless, it is a very compelling device. I’m still going to want physical copies of some books, but for most of the books I read I really don’t care what I read them on, so long as the medium disappears when I get into the story.
One last thing
Oh yes, one last thing, did I mention that the Kindle comes with free access to Wikipedia?
Searching for senior .NET developer to join us at Cargill Geneva
We are searching for a senior .NET developer with strong business skills to join our team at Cargill Geneva.
We are a small team of experienced developers, working closely with Traders and Analysts to understand their requirements and implement solutions from A-Z. We need people with very good interpersonal skills, that are comfortable dealing directly with demanding business users, and with solid development skills.
We use VS2008, .NET 3.5, linq, etc. No new technology for the sake of it, but if it makes sense then we use it.
If you are looking for a position that makes use of both your development skills and your business/domain knowledge then please apply. We are primarily looking for people from the Geneva area, but if you are elsewhere in Switzerland or in the EU then please apply.
Enter job GEN00575 at http://www.cargill.com/careers/search-apply/experienced-professionals/emea/index.jsp
Calling WCF Services from Excel VBA clients using the WCF Service Moniker
Did you know there is a way to invoke simple Windows Communication Foundation (WCF) Services from Excel VBA without installing anything other than the .NET Framework on the Excel machine?
There are many different kinds of monikers, but the one that interests us is the Service moniker that can be used to access WCF Services:
Set someObject = GetObject(“service:Binding Information”)
In this blog post I’m going to show how you how to go about using WCF Services from Excel VBA, step by step, from beginning to end, and explain how to debug the rather obtuse messages that Excel displays when you’ve misconfigured something.
The WCF Service
The WCF Interface you expose can not be particularly complex if you want to use the Service Moniker – I’ve found it best to keep top primitive types, and arrays of primitive types. Data Contracts seem to be a no-go.
Start by creating a new WCF Service using File|New|Project and selecting WCF Service Library:
Double-click on IService1.cs in the Solution Explorer, and replace the default contents with this simple interface:
using System; using System.ServiceModel; namespace WcfService1 { [ServiceContract] public interface IService1 { [OperationContract] string GetData(int value); [OperationContract] object[] GetSomeObjects(); } }
Next replace the contents of the service implementation, Service1.cs, with the following:
using System; namespace WcfService1 { public class Service1 : IService1 { public string GetData(int value) { return string.Format("You entered: {0}", value); } public object[] GetSomeObjects() { return new object[] { "String", 123, 44.55, DateTime.Now }; } } }
Configuring the WCF Service
By default the WCF Service is configured to use HTTP as the transport protocol. I generally switch it to use TCP, because I am operating within a corporate intranet, and HTTP seems like overkill.
You’ll also find that by default your WCF Service exposes two endpoints. The first exposes as you’d expect, the IService1 interface you defined above. The second exposes Metadata about your service, which the Service Moniker uses to know what operations are available on your service. You’ll need both.
Right-click on the App.config file in the Solution Explorer, and select Edit WCF Configuration:
Switch the first endpoint to use TCP:
Also change the second to use mexTcpBinding:
Change the base address that the service will use, to use a TCP address instead of a HTTP Address by selecting the Host node on the left hand tree, and then selecting the base address and clicking on Edit, and changing the text to be net.tcp://localhost:7891/Test/WcfService1/Service1/
Finally, because you are using TCP instead of HTTP, change the MetataData service to not expect to expose the metadata via HTTP, by changing HttpGetEnabled to False under Advanced|Service Behaviours…
Save the changes and exit the WCF Editor. Your App.config should look like this:
<?xml version="1.0" encoding="utf-8" ?> <configuration> <system.web> <compilation debug="true" /> </system.web> <system.serviceModel> <services> <service behaviorConfiguration="WcfService1.Service1Behavior" name="WcfService1.Service1"> <endpoint address="" binding="netTcpBinding" bindingConfiguration="" contract="WcfService1.IService1"> <identity> <dns value="localhost" /> </identity> </endpoint> <endpoint address="mex" binding="mexTcpBinding" bindingConfiguration="" contract="IMetadataExchange" /> <host> <baseAddresses> <add baseAddress="net.tcp://localhost:7891/Test/WcfService1/Service1/" /> </baseAddresses> </host> </service> </services> <behaviors> <serviceBehaviors> <behavior name="WcfService1.Service1Behavior"> <serviceMetadata httpGetEnabled="False"/> <serviceDebug includeExceptionDetailInFaults="False" /> </behavior> </serviceBehaviors> </behaviors> </system.serviceModel> </configuration>
To start running your service you can hit Ctrl-F5 in Visual Studio. This will start a test service host, and a test client. We will ignore the client, but you can check that the service host has started by clicking on the message in the notification area:
Eventually you’ll want to host your service somewhere else, such as a Windows Service.
The Excel VBA Client
Start Excel, and then hit Alt-F11 to enter the VBA Code editor. We’ll invoke the WCF Service whenever someone clicks on a cell in the first sheet. Double-click on Sheet1 on the top left hand side, and then select Worksheet from the drop down of objects:
The Service Moniker needs to know the address of the MetataData Service, the address of the service itself, binding information, and information about the contract.
Dim addr As String addr = "service:mexAddress=""net.tcp://localhost:7891/Test/WcfService1/Service1/Mex""," addr = addr + "address=""net.tcp://localhost:7891/Test/WcfService1/Service1/""," addr = addr + "contract=""IService1"", contractNamespace=""http://tempuri.org/""," addr = addr + "binding=""NetTcpBinding_IService1"", bindingNamespace=""http://tempuri.org/"""
Once you’ve built up the Service Moniker string, you can use GetObject to resolve it, and then invoke a method on it:
Dim service1 As Object Set service1 = GetObject(addr) MsgBox service1.GetData(12)
The VBA Editor should look like this:
I’ve set a breakpoint on the first line of code by clicking where the red circle is above.
If you now click on a cell in your sheet, and let the VBA code run, you should see this:
The VBA code has called through to the WCF Service and invoked a method on it, and the service has returned a string.
Change the code to invoke the second method, and step through in the debugger, and add a Watch on the result:
Whats up with the Tempuri?
You’ll have noticed that the moniker string references a couple of weird Tempuri namespaces. These are the defaults, but you can alter them. This can be useful if you have a single service exposing a couple of interfaces and you only want to work with one of them. For example your service may expose a complex interface for WPF clients, and a simple interface for a Excel client. If you give the simple interface a different namespace than the complex interface, you’ll be able to access it from Excel VBA.
To change the contract namespace, edit your interface code:
using System; using System.ServiceModel; namespace WcfService1 { [ServiceContract(Namespace="http://damianblog.com/")] public interface IService1 { [OperationContract] string GetData(int value); [OperationContract] object[] GetSomeObjects(); } }
Then your service moniker can be changed accordingly:
addr = addr + "contract=""IService1"", contractNamespace=""http://damianblog.com/"","
When it doesn’t work
The Excel message you get when the GetObject doesn’t work properly is not exactly detailed:
There is however a way of getting more detailed information. You can attach your debugger to Excel, and then see the underlying managed .NET exception.
To attach your debugger to Excel in Visual Studio use Debug|Attach to Process and then select Excel, and click Attach:
Next, make sure the debugger stops as soon as an exception occurs by clicking on Debug|Exceptions and check the checkbox to be interrupted when an exception is thrown:
Don’t forget that you have done this. If you leave it checked then later on when debugging unrelated code you may get thoroughly confused to have the debugger break inside framework code that throws and then handles an exception which is normally invisible to you.
You’ll also need to tell the debugger to break when code other than your own code throws an exception. Do this by clicking on Tools|Options and then going to the Debugging section, and uncheck the Enable Just My Code checkbox:
Now run your VBA code as usual, and when you get the error the Visual Studio Debugger will break with more detailed error information. So if I change my moniker string to use an invalid interface name the Excel VBA error is:
Whereas Visual Studio actually tells you what the error is:
The maximum message size quote for incoming messages has been exceeded
You’ll hit this error if your .NET code returns too much data to the Excel client. You might be able to resolve it by setting the MaxRecivedMessageSize property in an Excel.exe.config file in the same folder as Excel.exe. They way I have handled it is to move from using the Service Moniker mechanism, and to create a managed Excel AddIn that sets the maximum message size programmatically.
Summary
The WCF Service Moniker offers an excellent way for you to invoke simple WCF Interfaces, where small quantities of data are exchanged, without installing anything at all on the Excel Client machine.
In the above examples the service moniker created by the VBA code used the “localhost” address for the service, but if your service is running on another machine you can specify that machine’s address: the service can run anywhere.
Got a product idea? Don’t register the domain.
Since I started programming in the early eighties I’ve dreamed of ideas for software tools, utilities and products. I’ve followed through and created some of them, but for many I’ve not, and I think I’ve finally figured out why: it can only be because I registered the domain name before I created the product. Let me explain …
Having an idea for a product or web site can be enormously seductive. We can dream away, and if we never follow through, we can never fail. Even better we can tell others about our fantastic idea, and almost know what it would feel like if it was a success. Almost.
But the killer is that we can research domain names. We can spend hours trying to find exactly the right domain for our product-to-be. The one we haven’t even started creating yet. And finally, when we’ve got that perfect domain, we can pull out our credit card, and register it. Then, we are done. That’s it. No need to do anything else. Dreamed about the success, got the domain name, and then … well, there isn’t really any need to take it any further, is there?
This post isn’t just about the dangers of premature registration, it is also to allow me to put some of my own overly-enthusiastic registrations to rest. So here they are. None of them are real, except in my imagination (and of course in the domain name registration) …
- Asknearme.com : Transient, anonymous conversations. A GPS-enabled mobile-phone location-based service that is an anti-social networking site, where you could anonymously ask questions to anyone who happens to be close to you geographically: where are the closest toilets? Has anyone found a green hat?
- Askmystreet.com : do you know everyone on your street? Anyone? This site was to let you get in touch with people living near you, to help build physical communities out of virtual ones.
- tracejs.com, jsprof.com, jsprofiler.com, javascriptprofiler.com : this product idea used the JavaScript debugger API on windows to continuously break into JavaScript code running in Internet Explorer, and let you see what JavaScript code was executed, and how much time each function took. I got close on this one.
For balance, I have got it right a few times:
- mcefm.com – listen to Last.fm in Windows Media Center. I’ve stopped developing it since Last.fm cracked down on the use of their APIs in some countries.
- beebmc.com – listen to BBC Radio within Windows Media Center. Still exists, and still quite popular.
- j-integra.com (not mine any more) – Java-COM interoperability, initially through my Java implementation of the DCOM wire protocol.
- promptsql.com (not mine any more) – SQL Intellisense within Query Analyzer and SQL Server Management Studio
This post is a little tongue in cheek, although there is a kernel of truth. It is important to follow through on our ideas, and not just live on the dream. Don’t deflate the excitement by working on the incidental. Tackle the core first.
Stop that dreaming, and get coding.
