A couple of gotchas for creating Windows Phone 7 Applications

I have been doing Nathan’s Transforms and Animations projects. I made a typo when naming a Storyboard (note the space as the 1st character) and when I tried to auto-generate the code behind function:

image

I got this error:

image

Notice how there is a space between the ‘ and the P -> however, if you are typing/reading fast, you might miss it.

Another gotcha I found was in Chapter 16, when coding up the DoubleAnimationUsingKeyFrames. I copied the code verbatim from his book and I got this:

image

When I added an x:name, the compiler was once again happy.

My final gotcha looked like this:

image

And the offending line is in the LotteryBall.Percolating Setter:

Storyboard.SetTargetProperty(this.percolatingStoryboard, new PropertyPath("Y"));

WTF? How can you set a property path to a property that doesn’t exist? I ran the code sample and it works! Ugh, I am at a loss. He has a Y property in the Tilt class that I didn’t include because it is non-essential. Oh well, it would have been cool to see the final solution work…

Windows Phone 7 Certification

I submitted my 1st phone for certification last week.  It failed for 3 reasons:

1) Because I use the location service, I need to have a privacy policy.  I am sure some lawyers at MSFT cooked this one up – in any event since I don’t store or transmit the data my privacy policy is pretty vanilla.  I stuck it on the configuration page.  I am surprised that MSFT doesn’t look at the source code and determine if the location service is actually doing any transmission or storage.  I guess they are just doing a CYA.

2) I had some chrome in my screenshot.  It is kind of pain doing the screen shot because the GeoService does not work with the emulator so I have to rig up a faux-screen to use the snipping tool.  Oh well, I’ll do another one.

3) When the location service is disabled on the phone, the app does not handle it gracefully (it goes boom).  This is issue I am glad Microsoft caught – I didn’t know that the users can disable the location service in the settings of the phone.  I need to code around this problem by checking the status of the GeoLocationWatcher before calling any of its functions.  This issue makes me appreciate the certification process.

 

In any event, I plan to make these changes and release 1.1 by the end of the day.  Less blog, more code…

GetName() fails in Windows Phone 7

I am finishing up my 1st real windows phone application and I am creating an “About” page. Instead of hard-coding in the version number, I thought I would take a trick form my old WinForm days and use System.Reflection

I whipped up some code like this:

protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e) { this.VersionTextBlock.Text = String.Format("Version {0}", Assembly.GetExecutingAssembly(). GetName().Version.ToString()); base.OnNavigatedTo(e); }

I then ran it and got the following error:

image

Ugh. I was going to figure out what was wrong but then I deferred to the example in Chapter 6 in Adam Nathen’s 101 Windows Phone Apps . I changed the code to this:

protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e) { string fullAssemblyName = typeof(AboutPage).Assembly.ToString(); int firstComma = fullAssemblyName.IndexOf("Version="); int secondComma = fullAssemblyName.IndexOf(",", firstComma); string versionNumber = fullAssemblyName.Substring(firstComma, secondComma - firstComma); this.VersionTextBlock.Text = versionNumber; base.OnNavigatedTo(e); }

That worked fine.

Windows Phone 7 Design Time and Asynch Initialization

I am working on a Windows Phone 7 app and I ran into an interesting problem.  The architecture of the app is MVVM and the ViewModel is a ‘Threat’.  When consuming the ThreatViewModel in my Vi,ew I havew the following code:

image

This fails because the TheatViewModel created a proxy to consume a WCF service. I made the WCF-creating method, made it public, and called it during the initialization of the page:

public CurrentStatusView() { InitializeComponent(); ThreatViewModel threatViewModel = (ThreatViewModel)this.DataContext; threatViewModel.InitializeLocations(); }

The problem is that consuming the control – the initialize component gets called and this is the error message:

image

Since initialize component is getting called in deign time, the asynch is getting kicked off – and the designer is throwing an exception.  Rob Seder seems to think it is a .config issue – because the .config is not present in design time, the proxy doesn’t have the information to make the proxy call.

Stepping back, the proxy and asynch call needs to happen outside of the designer – at some point in the code behind to respond to an event on the screen. Perhaps application load or page load.  In any event, merging asycnh calls is not a good idea…

The power of separation

I am getting ready to deploy my 1st Windows Phone 7 app. The application consumes some data that is served up by a WCF service that I wrote. Until today, I had been testing the application using some dummy data that I hard-coded into the UI.

To add the WCF service, I added a new WCF project to my solution (and a supporting data project that uses Entity Frameworks). I ran into the same problem as I encountered last year that I forgot about – when you add a reference to a project that uses Entity Frameworks, you need to add a reference to System.Data.Entities in the consuming project. If not, you can see the business classes but the context will not work. Unfortunately, the only way to see this error it to hard-code the context into your consuming project, hit F5, and get this message:

'System.Data.Objects.DataClasses.EntityObject' is defined in an assembly that is not referenced. You must add a reference to assembly 'System.Data.Entity, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089'.

Once I figured that out, I whipped up a basic method using some LINQ like so:

public Location GetLocation(int locationId) { var q = from l in context.RoadAlert_Location where l.LocationId == locationId select l; return MapLocation(q.FirstOrDefault()); }

Easy enough, I then added my interface:

[ServiceContract(Namespace="http://schemas.tff.com/2011/06/13/RoadAlert.Services")] [ServiceKnownType(typeof(Location))] [ServiceKnownType(typeof(List<Location>))] public interface IRoadAlert { [OperationContract] Location GetLocation(int locationId); [OperationContract] List<Location> GetLocations(int alertTypeId); }

And then published the service to my WinHost server. It published fine and I got the WSDL no problem. However, after I added a reference, I could not create a proxy class. I checked the clientConfig and I was surprised because it was empty:

image

I did a quick search and found posts like this one. I made sure I was using BasicHTTPBinding like so:

image

However, it still was not working. I would see the service reference and the wizard exited with no errors. However, when I tried to create the proxy, I got an exception.

I then decided to take a step back and separate the service and data projects from my solution – instead of deplying to WinHost. I started the service project and then tried to add a reference from the client. Once I did that, I got this in my client config:

<configuration> <system.serviceModel> <bindings> <basicHttpBinding> <binding name="BasicHttpBinding_IRoadAlert" maxBufferSize="2147483647" maxReceivedMessageSize="2147483647"> <security mode="None" /> </binding> </basicHttpBinding> </bindings> <client> <endpoint address="http://localhost:52296/RoadAlert.svc" binding="basicHttpBinding" bindingConfiguration="BasicHttpBinding_IRoadAlert" contract="Tff.RoadAlert.Services.IRoadAlert" name="BasicHttpBinding_IRoadAlert" /> </client> </system.serviceModel> </configuration>

Magic! I have no idea why/how it now works, but separating the projects did the trick. I then could create my proxy locally. Then to deploy, I just published the service and changed the endpoint address on the client. I found this Microsoft page that details many of the problems and steps I went through.

Another interesting note is that you can’t do a synchronous call in Win Phones – I Guess they all have to be asynch…