2
votes

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?

4

4 Answers

3
votes

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.

1
votes

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 the using System.Windows.Navigation;)

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

0
votes

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.

0
votes

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.