Home > .NET, C#, MVVM, Windows Phone > Using “AndContinue” methods in Windows Phone Store apps with MVVM

Using “AndContinue” methods in Windows Phone Store apps with MVVM

07/01/2015

As MSDN says, “Certain memory-intensive API on Windows Phone 8.1 contain AndContinue methods. When you call an AndContinue method, your app is deactivated while the operation completes in order to conserve memory. On low-memory devices, your app might even be terminated. Because of this possibility, you have to call different methods in a Windows Phone Store app than you call in a Windows Store app to continue your app after these operations.”.

This happens, for example, when we want to select an image using the FilePicker. On Windows Phone Store apps, we need to call the PickSingleAndContinue method. In this case, we have the problem to continue our apps after calling this method.

The topic How to continue your Windows Phone Store app after calling an AndContinue method on MSDN introduces the ContinuationManager, a class that works together with the SuspensionManager to make it easier to continue our app.

This code, however, is based on a code-behind approach. If we’re following the MVVM pattern, we need to change it in order to invoke continuation methods on a ViewModel. So, we can rewrite the Continue method as follows:

public class ContinuationManager
{
    // ...
    
    private FrameworkElement GetCurrentView()
    {
        var frame = Window.Current.Content as Frame;
        if (frame != null)
            return frame.Content as FrameworkElement;

        return Window.Current.Content as FrameworkElement;
    }

    internal void Continue(IContinuationActivatedEventArgs args)
    {
        var view = this.GetCurrentView();
        if (view == null)
            return;

        this.Continue(args, view.DataContext);
    }

    internal void Continue(IContinuationActivatedEventArgs args, object dataContext)
    {
        if (args == null)
            throw new ArgumentNullException("args");

        if (this.args != null)
            throw new InvalidOperationException("Can't set args more than once");

        this.args = args;
        this.id = Guid.NewGuid();

        if (dataContext == null)
            return;

        switch (args.Kind)
        {
            case ActivationKind.PickFileContinuation:
                var fileOpenPickerViewModel = dataContext as IFileOpenPickerContinuable;
                if (fileOpenPickerViewModel != null)
                    fileOpenPickerViewModel.ContinueFileOpenPicker
                        (args as FileOpenPickerContinuationEventArgs);
                break;

            case ActivationKind.PickSaveFileContinuation:
                var fileSavePickerViewModel = dataContext as IFileSavePickerContinuable;
                if (fileSavePickerViewModel != null)
                    fileSavePickerViewModel.ContinueFileSavePicker
                        (args as FileSavePickerContinuationEventArgs);
                break;

            case ActivationKind.PickFolderContinuation:
                var folderPickerViewModel = dataContext as IFolderPickerContinuable;
                if (folderPickerViewModel != null)
                    folderPickerViewModel.ContinueFolderPicker
                        (args as FolderPickerContinuationEventArgs);
                break;

            case ActivationKind.WebAuthenticationBrokerContinuation:
                var wabViewModel = dataContext as IWebAuthenticationContinuable;
                if (wabViewModel != null)
                    wabViewModel.ContinueWebAuthentication
                        (args as WebAuthenticationBrokerContinuationEventArgs);
                break;
        }
    }
}

The GetForCurrentView method, at lines 5-12, retrieves the view (i.e., the page) that is currently shown. Then, in the Continue method at lines 23-67, we check the Kind property of IContinuationActivatedEventArgs (that comes from the OnActivated method of App.xaml.cs file): based on its value, we try to cast the DataContext of the page (i.e., its ViewModel) to a particular interface (that is declared below in the file).

If the conversion succeeds, it means that the ViewModel supports this kind of continuation, so the corresponding method is invoked. For example, in case of PickFileContinuation (lines 39-44), we cast the DataContext to IFileOpenPickerContinuable and then call its ContinueFileOpenPicker method passing information about the selected file.

In this way, our ViewModel looks like (the example is based on MVVM Light):

public class PhotoViewModel : ViewModelBase, IFileOpenPickerContinuable
{
    private string photoPath;
    public string PhotoPath
    {
        get { return photoPath; }
        set { this.Set(ref photoPath, value); }
    }

    public RelayCommand SelectPhotoCommand { get; set; }

    public PhotoViewModel()
    {
        this.CreateCommands();
    }

    private void CreateCommands()
    {
        SelectPhotoCommand = new RelayCommand(() =>
        {
            // Calls the method that opens the FilePicker page.
            // When selected, the method "ContinueFileOpenPicker"
            // from IFileOpenPickerContinuable interface
            // will be invoked.
            var picker = new FileOpenPicker();

            picker.SuggestedStartLocation = PickerLocationId.PicturesLibrary;
            picker.SettingsIdentifier = "continuationmanagerdemo";
            picker.ViewMode = PickerViewMode.List;
            picker.FileTypeFilter.Add(".jpg");

            picker.PickSingleFileAndContinue();
        });
    }

    public void ContinueFileOpenPicker(FileOpenPickerContinuationEventArgs args)
    {
        // The "args" object contains information about selected file(s).
        if (args.Files.Any())
        {
            var file = args.Files[0];
            PhotoPath = file.Path;
        }
        else
        {
            PhotoPath = null;
        }
    }
}

The SelectPhotoCommand (lines 19-33) calls the FileOpenPicker.PickSingleFileAndContinue method, that opens a page allowing the selection of a file (a JPG image, in this case). Thanks to the ContinuationManager, as the ViewModel implements the IFileOpenPickerContinuable interface, the ContinueFileOpenPicker method will be automatically invoked when the user selects a file. We retrieve the first one and save its Path property, so we can show it, for example, in an Image control that is bound to it.

You can download a working example of the ContinuationManger with MVVM using the link below:

Using AndContinue methods in Windows Phone Store apps with MVVM

Categories: .NET, C#, MVVM, Windows Phone
  1. 09/01/2015 at 00:12

    Reblogged this on Microsoft Visual Studio .NET.

  1. No trackbacks yet.
Comments are closed.
%d bloggers like this: