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
DownloadAll 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.
Blog comments
Ian Griffiths
09-Jul-2013 6:05