I’ve been exploring the Windows Phone 7 SDK in preparation for a launch event in New York next week by porting the CodeStock Android application to WP7 and I’ve run into a bit of a headscratcher.
The Android app uses a context menu option to permit the user to refresh the data from the website “on-demand” so I created an ApplicationBarIconButton (named “downloadScheduleButton” surprisingly enough) for the same functionality. On first test the app crashed with a null object reference on the line in the main page’s constructor added to wire-up the click handler. The line of code looks like this:
this.downloadScheduleButton.Click += new EventHandler(downloadScheduleButton_Click);
The null reference was “downloadScheduleButton” and yes, I did put the line after the call to InitializeComponent(). The generated SilverLight code for the page included this line in InitializeComponent:
this.downloadScheduleButton = ((Microsoft.Phone.Shell.ApplicationBarIconButton)(this
but FindName was returning null. The docs for FindName included this note:
"A run-time API such as FindName is working against an object tree. These objects are loaded into the content area and the CLR runtime engine of the overall Silverlight plug-in. When part of the object tree is created from templates or run-time loaded XAML, a XAML namescope is typically not contiguous with the entirety of that object tree. The result is that there might be a named object in the object tree that a given FindName call cannot find."
The docs continue by discussing using GetTemplateChild, VisualTreeHelper, or XamlReader.Load but none of the cases seem to apply here. Further, the ApplicationBarIconButton class doesn’t expose a Name property so I can’t write my own method to loop through buttons and matching by name.
I got around it by using
((ApplicationBarIconButton)this.ApplicationBar.Buttons).Click += new
but that’s awfully fragile and will break if the order of buttons is rearranged. What am I missing here?