Windows 8 XAML Tips - Detect App Deactivation

By Fons Sonnemans, posted on
2668 Views 1 Comments

Detecting when an Windows 8 Store app is deactivated isn't as easy as you would expect. In the Windows Phone project templates you get the Application_Launching(), Application_Activated(), Application_Deactivated() and Application_Closing() methods in the App.xaml.cs. But those methods don't exists in the Windows Store project templates. There is an OnSuspending() method but you can't use it to detect deactivation. You use it to store your data when suspending the app. This will problably go off a few seconds later than deactivation.

Solution

To solve this problem I have used the Activated event of the CoreWindow class. This event can also be used to detect deactivation inspite of it's name. The WindowActivatedEventArgs has a WindowActivationState property of the type CoreWindowActivationState. This enum holds the values CodeActivated, Deactivated and PointerActivated. This event also is fired when the app is closed.

Example

In the following example I have created an app in which a Timer updates a counter every second. In the constructor I have subscribed the page on the Activated event of the CoreWindow object using the GetForCurrentThread() method. The eventhandler stops the timer when the app is deactivead or closed. It restarts the timer when the app is activated again. The counter value is written to the LocalSettings on deactivation and close of the app. In the constructor of the MainPage the value is read from the LocalSettings so the app continues with the last used counter value.

public sealed partial class MainPage : Page {

    private DispatcherTimer _timer = new DispatcherTimer();
    private int _counter;
    private const string Key = "Counter";

    public MainPage() {
        this.InitializeComponent();

        this._timer.Interval = TimeSpan.FromSeconds(1);
        this._timer.Tick += _timer_Tick;

        object value;
        if (ApplicationData.Current.LocalSettings.Values.TryGetValue(Key, out value)) {
            _counter = (int)value;
            this.textBlockCounter.Text = _counter.ToString();
        }

        CoreWindow.GetForCurrentThread().Activated += MainPage_Activated;
    }

    void _timer_Tick(object sender, object e) {
        this._counter++;
        this.textBlockCounter.Text = _counter.ToString();
    }

    void MainPage_Activated(CoreWindow sender, WindowActivatedEventArgs args) {

        if (args.WindowActivationState == CoreWindowActivationState.Deactivated) {
            _timer.Stop();
            Windows.Storage.ApplicationData.Current.LocalSettings.Values[Key] = _counter;
        } else {
            _timer.Start();
        }
    }
}

The MainPage.xaml only contains a Grid and the TextBox which displays the counter value.

<Page
    x:Class="DetectAppDeactivation.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:DetectAppDeactivation"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d">

    <Grid Background="{StaticResource ApplicationPageBackgroundThemeBrush}">
        <TextBlock x:Name="textBlockCounter"
                   Text="0"
                   FontSize="150"
                   VerticalAlignment="Center"
                   HorizontalAlignment="Center" />
    </Grid>
</Page>

Closure and download

I hope you like my solution. You can download my code here.

Cheers,

Fons

Download

All postings/content on this blog are provided "AS IS" with no warranties, and confer no rights. All entries in this blog are my opinion and don't necessarily reflect the opinion of my employer or sponsors. The content on this site is licensed under a Creative Commons Attribution By license.

Leave a comment

Blog comments

Ian Griffiths

09-Jul-2013 6:05
Some (myself included) did not find it obvious that deactivation doesn't necessarily mean your application has gone anywhere. For example, simply pressing WindowsKey+Tab (which brings up the list of Store apps currently running and lets you switch between them - sort of store app verion of Alt Tab) causes your application to be deactivated immediately, even if you don't actually switch to a different app! (You get reactivated again if the user decides not to switch anywhere.) Also, if snapping is in use, simply moving the focus to the other app will cause your app to be deactivated. If you want to know whether your application has been taken completely out of sight, then the core window also offers visibility events. Those turned out to do what I had initially thought activation events would do for me. (Makes sense with hindsight, it just wasn't what I first thought.)