/// <summary>
        /// Implementation of the install application command.
        /// </summary>
        /// <returns>Task object used for tracking method completion.</returns>
        private async Task InstallAppAsync()
        {
            // Prompt the user for the required file.
            AppInstallFiles installFiles = new AppInstallFiles();
            ContentDialog   dialog       = new GetAppInstallFilesDialog(installFiles);
            await dialog.ShowAsync();

            if (installFiles.AppPackageFile == null)
            {
                return;
            }

            foreach (DeviceMonitorControl monitor in this.GetCopyOfRegisteredDevices())
            {
                DeviceMonitorControlViewModel viewModel = monitor.ViewModel;
                if (!viewModel.IsSelected)
                {
                    continue;
                }

                // Assigning the return value of InstallAppAsync to a Task object to avoid
                // warning 4014 (call is not awaited).
                Task t = monitor.InstallAppAsync(installFiles);
            }
        }
        /// <summary>
        /// Implementation of the forget connections command.
        /// </summary>
        /// <returns>Task object used for tracking method completion.</returns>
        private async Task ForgetAllConnectionsAsync()
        {
            YesNoMessageDialog messageDialog = new YesNoMessageDialog(
                "Are you sure you want to unregister the selected devices?");

            if (MessageDialogButtonId.Yes != await messageDialog.ShowAsync())
            {
                return;
            }

            this.suppressSave = true;

            foreach (DeviceMonitorControl monitor in this.GetCopyOfRegisteredDevices())
            {
                DeviceMonitorControlViewModel viewModel = (DeviceMonitorControlViewModel)monitor.DataContext;
                if (viewModel.IsSelected)
                {
                    monitor.Disconnect();
                    this.RegisteredDevices.Remove(monitor);
                }
            }

            this.suppressSave = false;

            await this.SaveConnectionsAsync();

            this.StatusMessage = string.Empty;
        }
        /// <summary>
        /// Compare two DeviceMonitorControl objects.
        /// </summary>
        /// <param name="x">The DeviceMonitorControl object.</param>
        /// <param name="x">The DeviceMonitorControl object which will be compared to x.</param>
        /// <returns>0 if the objects are equivalent, 1 if x sorts in front of y, -1 otherwise.</returns>
        public int Compare(DeviceMonitorControl x, DeviceMonitorControl y)
        {
            // Get the view model for each device
            DeviceMonitorControlViewModel xViewModel = (DeviceMonitorControlViewModel)x.DataContext;
            DeviceMonitorControlViewModel yViewModel = (DeviceMonitorControlViewModel)y.DataContext;

            // Sort by name
            int comparisonResult = string.Compare(
                xViewModel.Name,
                yViewModel.Name);

            if (string.IsNullOrWhiteSpace(xViewModel.Name) ||
                string.IsNullOrWhiteSpace(yViewModel.Name))
            {
                // Sort empty names last
                comparisonResult = -(comparisonResult);
            }

            if (0 == comparisonResult)
            {
                // Names were equivalent, sort by address
                comparisonResult = string.Compare(
                    xViewModel.Address,
                    yViewModel.Address);
            }

            return(comparisonResult);
        }
        /// <summary>
        /// Implementation of the save session file command.
        /// </summary>
        private async Task SaveSessionFile()
        {
            this.ClearStatusMessage();

            try
            {
                // Use the picker to select the target location.
                FileSavePicker savePicker = new FileSavePicker();
                savePicker.FileTypeChoices.Add("Windows Mixed Reality Commander session file", new List <String>()
                {
                    ".xml"
                });
                savePicker.DefaultFileExtension = ".xml";

                StorageFile file = await savePicker.PickSaveFileAsync();

                if (file == null)
                {
                    return;
                }

                List <ConnectionInformation> sessionDevices = new List <ConnectionInformation>();
                foreach (DeviceMonitorControl monitorControl in this.GetCopyOfRegisteredDevices())
                {
                    DeviceMonitorControlViewModel viewModel = (DeviceMonitorControlViewModel)monitorControl.DataContext;
                    sessionDevices.Add(
                        new ConnectionInformation(
                            viewModel.Address,
                            viewModel.Name));
                }

                // Serializing to a memory stream and writing the file using the FileIO class to ensure
                // that, if overwriting an existing file, all previous contents are removed.
                using (MemoryStream stream = new MemoryStream())
                {
                    XmlSerializer serializer = new XmlSerializer(typeof(List <ConnectionInformation>));
                    serializer.Serialize(stream, sessionDevices);
                    stream.Position = 0;

                    using (StreamReader reader = new StreamReader(stream))
                    {
                        string data = await reader.ReadToEndAsync();

                        await FileIO.WriteTextAsync(file, data);
                    }
                }

                this.StatusMessage = string.Format(
                    "Session file saved as {0}",
                    file.Path);
            }
            catch
            {
                this.StatusMessage = "Failed to save the session file.";
            }
        }
        /// <summary>
        /// Implementation of wipe camera roll command
        /// </summary>
        private async void WipeCameraRoll()
        {
            foreach (DeviceMonitorControl monitor in this.GetCopyOfRegisteredDevices())
            {
                DeviceMonitorControlViewModel monitorViewModel = monitor.ViewModel;

                if ((monitorViewModel.Filter & DeviceFilters.HoloLens) == DeviceFilters.HoloLens)
                {
                    await monitor.WipeCameraRollAsync();
                }
            }
        }
        /// <summary>
        /// Implementation of the refresh common applications command.
        /// </summary>
        /// <returns>Task object used for tracking method completion.</returns>
        private async Task RefreshCommonAppsAsync()
        {
            // Early exit if refresh has been suppressed.
            if (this.suppressRefreshCommonApps)
            {
                return;
            }

            this.StatusMessage = "Refreshing common applications";

            List <string> commonAppNames = new List <string>();

            foreach (DeviceMonitorControl monitor in this.GetCopyOfRegisteredDevices())
            {
                DeviceMonitorControlViewModel viewModel = monitor.ViewModel;
                if (!viewModel.IsSelected)
                {
                    continue;
                }

                List <string> deviceAppNames = await monitor.GetInstalledAppNamesAsync();

                // If this is the first device queried...
                if (commonAppNames.Count == 0)
                {
                    // ... Add all apps.
                    commonAppNames.AddRange(deviceAppNames);
                }
                else
                {
                    List <string> appNamesToRemove = new List <string>();

                    // Remove apps that do not exist on this device.
                    foreach (string name in commonAppNames)
                    {
                        if (!deviceAppNames.Contains(name))
                        {
                            appNamesToRemove.Add(name);
                        }
                    }

                    foreach (string name in appNamesToRemove)
                    {
                        commonAppNames.Remove(name);
                    }
                }
            }

            this.UpdateCommonAppsCollection(commonAppNames);

            this.StatusMessage = string.Empty;
        }
        /// <summary>
        /// Implementation of the stop mixed reality recording command.
        /// </summary>
        private void StopMixedRealityRecording()
        {
            foreach (DeviceMonitorControl monitor in this.GetCopyOfRegisteredDevices())
            {
                DeviceMonitorControlViewModel monitorViewModel = monitor.ViewModel;

                if ((monitorViewModel.Filter & DeviceFilters.HoloLens) == DeviceFilters.HoloLens)
                {
                    // Assigning the return value of StopMixedRealityRecordingAsync
                    // to a Task object to avoid warning 4014 (call is not awaited).
                    Task t = monitor.StopMixedRealityRecordingAsync();
                }
            }
        }
        /// <summary>
        /// Implementation of the save mixed reality files command.
        /// </summary>
        /// <returns>Task object used for tracking method completion.</returns>
        private async Task SaveMixedRealityFiles()
        {
            // We save images and videos in a subfolder of the pictures library.
            StorageFolder picturesLibrary = KnownFolders.PicturesLibrary;
            StorageFolder folder          = await picturesLibrary.CreateFolderAsync(
                MixedRealityFilesFolderName,
                CreationCollisionOption.OpenIfExists);

            foreach (DeviceMonitorControl monitor in this.GetCopyOfRegisteredDevices())
            {
                DeviceMonitorControlViewModel monitorViewModel = monitor.ViewModel;

                if ((monitorViewModel.Filter & DeviceFilters.HoloLens) == DeviceFilters.HoloLens)
                {
                    await monitor.GetMixedRealityFilesAsync(
                        folder,
                        this.DeleteMixedRealityFilesAfterSave);
                }
            }
        }
        /// <summary>
        /// Implementation of the select all devices command.
        /// </summary>
        private void SelectAllDevices()
        {
            // Suppress the refresh call that occurs in the SelectionChanged event handler.
            this.suppressRefreshCommonApps = true;

            foreach (DeviceMonitorControl monitor in this.GetCopyOfRegisteredDevices())
            {
                DeviceMonitorControlViewModel monitorViewModel = monitor.ViewModel;
                if ((monitorViewModel.Filter & this.SelectionFilter) == monitorViewModel.Filter)
                {
                    monitorViewModel.IsSelected = true;
                }
            }

            // Assigning the return value of RefreshCommonAppsAsync to a Task object to avoid
            // warning 4014 (call is not awaited).
            Task t = this.RefreshCommonAppsAsync();

            // Restore the nominal behavior of the SelectionChanged event handler.
            this.suppressRefreshCommonApps = false;
        }
        /// <summary>
        /// Registers the DeviceMonitor with the application.
        /// </summary>
        /// <param name="monitor">Device to register.</param>
        /// <param name="name">Descriptive name of the device.</param>
        /// <returns>Task object used for tracking method completion.</returns>
        private async Task RegisterDeviceAsync(
            DeviceMonitor monitor,
            string name)
        {
            DeviceMonitorControl deviceMonitorControl = new DeviceMonitorControl(monitor);

            deviceMonitorControl.AppInstalled       += DeviceMonitorControl_AppInstalled;
            deviceMonitorControl.AppUninstalled     += DeviceMonitorControl_AppUninstalled;
            deviceMonitorControl.DeviceDisconnected += DeviceMonitorControl_Disconnected;
            deviceMonitorControl.SelectedChanged    += DeviceMonitorControl_SelectedChanged;
            deviceMonitorControl.TagChanged         += DeviceMonitorControl_TagChanged;

            DeviceMonitorControlViewModel viewModel = deviceMonitorControl.DataContext as DeviceMonitorControlViewModel;

            viewModel.Name = name;

            // We want a sorted list of devices.
            List <DeviceMonitorControl> currentDevices = this.GetCopyOfRegisteredDevices();

            currentDevices.Add(deviceMonitorControl);
            currentDevices.Sort(new DeviceMonitorControlComparer());

            this.RegisteredDevices.Clear();
            foreach (DeviceMonitorControl monitorControl in currentDevices)
            {
                this.RegisteredDevices.Add(monitorControl);
            }
            if (this.RegisteredDevices.Count > 0)
            {
                this.HaveRegisteredDevices = true;
            }

            currentDevices.Clear();
            currentDevices = null;

            await this.SaveConnectionsAsync();
        }
        /// <summary>
        /// Saves device connections to disk.
        /// </summary>
        /// <returns>Task object used for tracking method completion.</returns>
        private async Task SaveConnectionsAsync()
        {
            if (this.suppressSave)
            {
                return;
            }

            List <ConnectionInformation> connections = new List <ConnectionInformation>();

            foreach (DeviceMonitorControl monitor in this.GetCopyOfRegisteredDevices())
            {
                DeviceMonitorControlViewModel monitorViewModel = monitor.ViewModel;

                connections.Add(new ConnectionInformation(
                                    monitorViewModel.Address,
                                    monitorViewModel.Name));
            }

            try
            {
                StorageFile connectionsFile = await this.localFolder.CreateFileAsync(
                    MainPage.ConnectionsFileName,
                    CreationCollisionOption.ReplaceExisting);

                using (Stream stream = await connectionsFile.OpenStreamForWriteAsync())
                {
                    XmlSerializer serializer = new XmlSerializer(typeof(List <ConnectionInformation>));
                    serializer.Serialize(stream, connections);
                    await stream.FlushAsync();
                }
            }
            catch
            {
                this.StatusMessage = "Failed to save connection information";
            }
        }
        /// <summary>
        /// Registers the DeviceMonitor with the application.
        /// </summary>
        /// <param name="monitor">Device to register.</param>
        /// <param name="name">Descriptive name of the device.</param>
        /// <returns>Task object used for tracking method completion.</returns>
        private async Task RegisterDeviceAsync(
            DeviceMonitor monitor,
            string name)
        {
            DeviceMonitorControl deviceMonitorControl = new DeviceMonitorControl(monitor);

            deviceMonitorControl.AppInstalled       += DeviceMonitorControl_AppInstalled;
            deviceMonitorControl.AppUninstalled     += DeviceMonitorControl_AppUninstalled;
            deviceMonitorControl.DeviceDisconnected += DeviceMonitorControl_Disconnected;
            deviceMonitorControl.SelectedChanged    += DeviceMonitorControl_SelectedChanged;
            deviceMonitorControl.TagChanged         += DeviceMonitorControl_TagChanged;

            DeviceMonitorControlViewModel viewModel = deviceMonitorControl.DataContext as DeviceMonitorControlViewModel;

            viewModel.Name = name;

            this.RegisteredDevices.Add(deviceMonitorControl);
            if (this.RegisteredDevices.Count > 0)
            {
                this.HaveRegisteredDevices = true;
            }

            await this.SaveConnectionsAsync();
        }