views:

169

answers:

4

I can't get the ApplicationBarIconButton's click event to fire under certain conditions.

I tried to simplify the steps required to reproduce it:

1) Create a new Windows Phone Application

2) Add a new Page (Page1.xaml)

3) Add a simple button on MainPage.xaml launching a PhotoChooserTask and navigate to Page1.xaml on the Completed event

public partial class MainPage : PhoneApplicationPage
{
    PhotoChooserTask photo;

    public MainPage()
    {
        InitializeComponent();
        photo = new PhotoChooserTask();
        photo.Completed += OnCameraCaptureTaskCompleted;
    }

    void OnCameraCaptureTaskCompleted(object sender, PhotoResult args)
    {
        this.NavigationService.Navigate(new Uri("/Page1.xaml", UriKind.Relative));
    }

    private void button1_Click(object sender, RoutedEventArgs e)
    {
        photo.Show();
    }
}

6) Uncomment the ApplicationBar section of Page1.xaml and set the click event of one of the buttons to a new event handler

<phone:PhoneApplicationPage.ApplicationBar>
    <shell:ApplicationBar IsVisible="True">
        <shell:ApplicationBarIconButton IconUri="/Images/appbar_button1.png" Text="Won't work" Click="ApplicationBarIconButton_Click" />
    </shell:ApplicationBar>
</phone:PhoneApplicationPage.ApplicationBar>

    private void ApplicationBarIconButton_Click(object sender, EventArgs e)
    {
        MessageBox.Show("This messagebox won't show!");
    }

Launch it

Click on the button to select a picture => you are redirected to Page1.xaml

Click on the ApplicationBarIconButton button : the event isn't fired!

Did I miss something or that's a bug?

A: 

I belive it has something to do with mix of chooser and the appbar. ApplicationBar is not a Silverlight control since maybe there is a bug with wiring it after toombstoning. Have you tried it on the device? there are some difference between them.

lukas
Yes, I tried on my LG developer device running with the RTM firmware and it behaves exactly the same.
Olivier PAYEN
This is really concerning! I've experimented with click events on menu buttons and menu items on both forms in your example and none of them fire after the chooser has returned. Off to experiment more.
Matt Lacey
Im 90% sure it is a bug. Please post it on the developer's forum or contact the team.
lukas
+1  A: 

After some digging around, this is due to some weird behaviour in the completed event.

As a workaround you can force the navigation in the completed event to run on the UI thread and all is OK.

    void OnCameraCaptureTaskCompleted(object sender, PhotoResult args)
    {
        Dispatcher.BeginInvoke(() =>
              this.NavigationService.Navigate(new Uri("/Page1.xaml", UriKind.Relative)));
    }

There are other limitations on things you can do in completed events as well. This is important to be aware of!

There may be (hopefully is) a good reason for this behaviour but it could do with being better documented.

Matt Lacey
Thanks for the workaround, it works perfectly. It sure could be more documented. I'm going to post it on the dev forum.
Olivier PAYEN
A: 

Interesting quirk.

The callback occurs on the UI thread. Using the Dispatcher defers the navigation until after the UI thread has finished its current activities. It looks like some component is not initialized properly before the second page has been instantiated. This is a bug.

Cheers,

Daniel

http://twitter.com/dbvaughan

Daniel Vaughan
A: 

After posting that question on the WP7 official forum (here is the link to the question), I had a response telling that it's a known issue.

Here is what seems to be the "official" workaround:

    void OnCameraCaptureTaskCompleted(object sender, PhotoResult args)
    {
        //Delay navigation until the first navigated event
        NavigationService.Navigated += new NavigatedEventHandler(navigateCompleted);
    }

    void navigateCompleted(object sender, EventArgs e)
    {
        //Do the delayed navigation from the main page
        this.NavigationService.Navigate(new Uri("/Page1.xaml", UriKind.Relative));
        NavigationService.Navigated -= new NavigatedEventHandler(navigateCompleted);
    }

(you'll need to add "using System.Windows.Navigation;")

Matt's workaround works too but I prefer using the NavigatedEventHandler than the Dispatcher.BeginInvoke solution.

Olivier PAYEN