Beispiel #1
0
        private async void DevicePicker_DeviceSelected(DevicePicker sender, DeviceSelectedEventArgs args)
        {
            await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, async() =>
            {
                // 更新 picker 上設備的 status
                sender.SetDisplayStatus(args.SelectedDevice, "connecting", DevicePickerDisplayStatusOptions.ShowProgress);

                // 取得目前選到設備的資訊
                activeDevice = args.SelectedDevice;

                // 現在 view 的 Id 與 CoreDispatcher
                int currentViewId = ApplicationView.GetForCurrentView().Id;
                CoreDispatcher currentDispatcher = Window.Current.Dispatcher;

                // 建立新的 view,
                if (projectionInstance.ProjectionViewPageControl == null)
                {
                    await CoreApplication.CreateNewView().Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () =>
                    {
                        // 建立新 viewe 的生命管理器
                        projectionInstance.ProjectionViewPageControl = ViewLifetimeControl.CreateForCurrentView();
                        projectionInstance.MainViewId = currentViewId;

                        var rootFrame = new Frame();
                        rootFrame.Navigate(typeof(ProjectionPage), projectionInstance);

                        // 這裏的 Window 代表是新建立這個 view 的 Window
                        // 但是要等到呼叫 ProjectionManager.StartProjectingAsync 才會顯示
                        Window.Current.Content = rootFrame;
                        Window.Current.Activate();
                    });
                }

                // 直接切換到指定的 view id
                //bool viewShown = await ApplicationViewSwitcher.TryShowAsStandaloneAsync(projectionInstance.ProjectionViewPageControl.Id);

                // 通知要使用新的 view
                projectionInstance.ProjectionViewPageControl.StartViewInUse();

                try
                {
                    txtViewId.Text = $"{projectionInstance.ProjectionViewPageControl.Id}, {currentViewId}";
                    await ProjectionManager.StartProjectingAsync(projectionInstance.ProjectionViewPageControl.Id, currentViewId, activeDevice);

                    player.Pause();

                    sender.SetDisplayStatus(args.SelectedDevice, "connected", DevicePickerDisplayStatusOptions.ShowDisconnectButton);
                }
                catch (Exception ex)
                {
                    sender.SetDisplayStatus(args.SelectedDevice, ex.Message, DevicePickerDisplayStatusOptions.ShowRetryButton);
                    if (ProjectionManager.ProjectionDisplayAvailable == false)
                    {
                        throw;
                    }
                }
            });
        }
        private async void Picker_DeviceSelected(DevicePicker sender, DeviceSelectedEventArgs args)
        {
            string deviceId = args.SelectedDevice.Id;

            //Casting must occur from the UI thread.  This dispatches the casting calls to the UI thread.
            await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, async() =>
            {
                //Update the display status for the selected device to connecting.
                picker.SetDisplayStatus(args.SelectedDevice, "Connecting", DevicePickerDisplayStatusOptions.ShowProgress);

                // BUG: In order to support debugging it is best to retreive the device from the local app instead
                // of continuing to use the DeviceInformation instance that is proxied from the picker.
                DeviceInformation device = null;
                try { if (deviceId.IndexOf("dial", StringComparison.OrdinalIgnoreCase) == -1)
                      {
                          device = await DeviceInformation.CreateFromIdAsync(deviceId, RequiredDeviceProperties.Props, DeviceInformationKind.DeviceContainer);
                      }
                } catch { }
                try { if (device == null)
                      {
                          device = await DeviceInformation.CreateFromIdAsync(deviceId, RequiredDeviceProperties.Props, DeviceInformationKind.AssociationEndpoint);
                      }
                } catch { }
                // In case the workaround did not work
                if (device == null)
                {
                    device = args.SelectedDevice;
                }

                //Try casting using DIAL first
                bool castSucceeded = await TryLaunchDialAppAsync(device);
                //If DIAL did not work for the selected device, try the CAST API
                if (!castSucceeded)
                {
                    castSucceeded = await TryCastMediaElementAsync(device);
                }

                if (castSucceeded)
                {
                    //Update the display status for the selected device.
                    try { picker.SetDisplayStatus(device, "Connected", DevicePickerDisplayStatusOptions.ShowDisconnectButton); } catch { }
                    disconnectButton.IsEnabled = true;

                    // Hide the picker now that all the work is completed
                    //picker.Hide();
                }
                else
                {
                    //Show a retry button when connecting to the selected device failed.
                    picker.SetDisplayStatus(device, "Connecting failed", DevicePickerDisplayStatusOptions.ShowRetryButton);
                }
            });
        }
        private async void Picker_DeviceSelected(DevicePicker sender, DeviceSelectedEventArgs args)
        {
            string deviceId = args.SelectedDevice.Id;

            //Casting must occur from the UI thread.  This dispatches the casting calls to the UI thread.
            await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, async() =>
            {
                //Update the display status for the selected device to connecting.
                try { picker.SetDisplayStatus(args.SelectedDevice, "Connecting", DevicePickerDisplayStatusOptions.ShowProgress); } catch { }

                //The selectedDeviceInfo instance is needed to be able to update the picker.
                DeviceInformation selectedDeviceInfo = args.SelectedDevice;
#if DEBUG
                // The args.SelectedCastingDevice is proxied from the picker process. The picker process is
                // dismissmed as soon as you break into the debugger. Creating a non-proxied version
                // allows debugging since the proxied version stops working once the picker is dismissed.
                selectedDeviceInfo = await DeviceInformation.CreateFromIdAsync(args.SelectedDevice.Id);
#endif

                bool castSucceeded = false;

                // If the ProjectionManager API did not work and the device id will have 'dial' in it.
                castSucceeded = await TryLaunchDialAppAsync(selectedDeviceInfo);

                // If it doesn't try the ProjectionManager API.
                if (!castSucceeded)
                {
                    castSucceeded = await TryProjectionManagerCastAsync(selectedDeviceInfo);
                }

                //If DIAL and ProjectionManager did not work for the selected device, try the CAST API
                if (!castSucceeded)
                {
                    castSucceeded = await TryCastMediaElementAsync(selectedDeviceInfo);
                }

                if (castSucceeded)
                {
                    //Update the display status for the selected device.  Try Catch in case the picker is not visible anymore.
                    try { picker.SetDisplayStatus(selectedDeviceInfo, "Connected", DevicePickerDisplayStatusOptions.ShowDisconnectButton); } catch { }

                    // Hide the picker now that all the work is completed. Try Catch in case the picker is not visible anymore.
                    try { picker.Hide(); } catch { }
                }
                else
                {
                    //Show a retry button when connecting to the selected device failed.
                    try { picker.SetDisplayStatus(selectedDeviceInfo, "Connecting failed", DevicePickerDisplayStatusOptions.ShowRetryButton); } catch { }
                }
            });
        }
Beispiel #4
0
        private async Task StopProjection(DevicePicker sender, DeviceInformation device)
        {
            // 關閉新建立的 view
            projectionInstance.Content.StopProjection();

            //Update the display status for the selected device.
            sender.SetDisplayStatus(device, "Disconnecting", DevicePickerDisplayStatusOptions.ShowProgress);

            //Update the display status for the selected device.
            sender.SetDisplayStatus(device, "Disconnected", DevicePickerDisplayStatusOptions.None);

            // Set the active device variables to null
            activeDevice = null;
        }
        private async void Picker_DeviceSelected(DevicePicker sender, DeviceSelectedEventArgs args)
        {
            string deviceId = args.SelectedDevice.Id;

            //Casting must occur from the UI thread.  This dispatches the casting calls to the UI thread.
            await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, async() =>
            {
                //Update the display status for the selected device to connecting.
                picker.SetDisplayStatus(args.SelectedDevice, "Connecting", DevicePickerDisplayStatusOptions.ShowProgress);

                // BUG: In order to support debugging it is best to retreive the device from the local app instead
                // of continuing to use the DeviceInformation instance that is proxied from the picker.
                DeviceInformation device = await DeviceInformation.CreateFromIdAsync(deviceId);

                bool castSucceeded = false;

                // The dial AssociationEndpoint ID will have 'dial' in the string.
                // If it doesn't try the ProjectionManager API.
                if (deviceId.IndexOf("dial", StringComparison.OrdinalIgnoreCase) == -1)
                {
                    castSucceeded = await TryProjectionManagerCastAsync(device);
                }
                // If the ProjectionManager API did not work and the device id will have 'dial' in it.
                if (!castSucceeded && deviceId.IndexOf("dial", StringComparison.OrdinalIgnoreCase) > -1)
                {
                    castSucceeded = await TryLaunchDialAppAsync(device);
                }

                //If DIAL and ProjectionManager did not work for the selected device, try the CAST API
                if (!castSucceeded)
                {
                    castSucceeded = await TryCastMediaElementAsync(device);
                }

                if (castSucceeded)
                {
                    //Update the display status for the selected device.  Try Catch in case the picker is not visible anymore.
                    try { picker.SetDisplayStatus(device, "Connected", DevicePickerDisplayStatusOptions.ShowDisconnectButton); } catch { }

                    // Hide the picker now that all the work is completed. Try Catch in case the picker is not visible anymore.
                    try { picker.Hide(); } catch { }
                }
                else
                {
                    //Show a retry button when connecting to the selected device failed.
                    try { picker.SetDisplayStatus(device, "Connecting failed", DevicePickerDisplayStatusOptions.ShowRetryButton); } catch { }
                }
            });
        }
Beispiel #6
0
        private void Picker_DeviceSelected(DevicePicker sender, DeviceSelectedEventArgs args)
        {
            // Getting the selected device
            _selectedDeviceInformation = args.SelectedDevice;

            // Save a setting locally on the device
            ApplicationDataContainer localSettings = Windows.Storage.ApplicationData.Current.LocalSettings;

            localSettings.Values[SelectedDeviceKey] = _selectedDeviceInformation.Id;

            _onDeviceSelected(_selectedDeviceInformation.Id);

            // Set status to Connecting
            _picker.SetDisplayStatus(args.SelectedDevice, "", DevicePickerDisplayStatusOptions.None);
        }
Beispiel #7
0
        private async void DevicePicker_DisconnectButtonClicked(DevicePicker sender, DeviceDisconnectButtonClickedEventArgs args)
        {
            await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () =>
            {
                // 關閉新建立的 view
                projectionInstance.Content.StopProjection();

                //Update the display status for the selected device.
                sender.SetDisplayStatus(args.Device, "Disconnecting", DevicePickerDisplayStatusOptions.ShowProgress);

                //Update the display status for the selected device.
                sender.SetDisplayStatus(args.Device, "Disconnected", DevicePickerDisplayStatusOptions.None);

                // Set the active device variables to null
                activeDevice = null;
            });
        }
Beispiel #8
0
        private async void Picker_DisconnectButtonClicked(DevicePicker sender, DeviceDisconnectButtonClickedEventArgs args)
        {
            //Casting must occur from the UI thread.  This dispatches the casting calls to the UI thread.
            await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, async() =>
            {
                rootPage.NotifyUser("Disconnect Button clicked", NotifyType.StatusMessage);

                //Update the display status for the selected device.
                sender.SetDisplayStatus(args.Device, "Disconnecting", DevicePickerDisplayStatusOptions.ShowProgress);

                bool disconnected = false;
                if (this.activeCastConnectionHandler is ProjectionViewBroker)
                {
                    disconnected = TryStopProjectionManagerAsync((ProjectionViewBroker)activeCastConnectionHandler);
                }
                if (this.activeCastConnectionHandler is DialApp)
                {
                    disconnected = await TryStopDialAppAsync((DialApp)activeCastConnectionHandler);
                }
                if (this.activeCastConnectionHandler is CastingConnection)
                {
                    disconnected = await TryDisconnectCastingSessionAsync((CastingConnection)activeCastConnectionHandler);
                }

                if (disconnected)
                {
                    //Update the display status for the selected device.
                    try { sender.SetDisplayStatus(args.Device, "Disconnected", DevicePickerDisplayStatusOptions.None); } catch { }
                    // Set the active device variables to null
                    activeDevice = null;
                    activeCastConnectionHandler = null;

                    //Hide the picker
                    sender.Hide();
                }
                else
                {
                    //Update the display status for the selected device.
                    sender.SetDisplayStatus(args.Device, "Disconnect failed", DevicePickerDisplayStatusOptions.ShowDisconnectButton);
                }
            });
        }
Beispiel #9
0
        private async Task StopDialConnection(DevicePicker picker, DeviceInformation device)
        {
            try
            {
                // 取得被選擇的 dial device
                DialDevice selectedDialDevice = await DialDevice.FromIdAsync(device.Id);

                // 更新 picker status
                picker.SetDisplayStatus(device, "connecting", DevicePickerDisplayStatusOptions.ShowProgress);
                // 取得 dial app
                DialApp app = selectedDialDevice.GetDialApp("castingsample");

                // 請求斷綫
                DialAppStopResult result = await app.StopAsync();

                if (result == DialAppStopResult.Stopped)
                {
                    picker.SetDisplayStatus(device, "Disconnected", DevicePickerDisplayStatusOptions.None);
                    activeDevice = null;
                    picker.Hide();
                }
                else
                {
                    if (result == DialAppStopResult.StopFailed || result == DialAppStopResult.NetworkFailure)
                    {
                        // 如果失敗的話要記得多 retry 的機制
                        picker.SetDisplayStatus(device, "Error", DevicePickerDisplayStatusOptions.ShowDisconnectButton);
                    }
                    else
                    {
                        // 如果設備沒有支援 Stop 機制,則直接清楚連綫就好
                        activeDevice = null;
                    }
                }
            }
            catch (Exception ex)
            {
            }
        }
Beispiel #10
0
        private async Task SendDialParameter(DevicePicker sender, DeviceSelectedEventArgs args)
        {
            try
            {
                // 設定遠端設備現在要準備連綫
                sender.SetDisplayStatus(args.SelectedDevice, "connecting", DevicePickerDisplayStatusOptions.ShowProgress);

                // 取得遠端設備中支援指定 app name 的 App
                DialDevice dialDevice = await DialDevice.FromIdAsync(args.SelectedDevice.Id);

                DialApp app = dialDevice.GetDialApp("castingsample");

                if (app == null)
                {
                    // 嘗試建立 DIAL device,如果失敗代表那個設備不支援 DIAL
                    sender.SetDisplayStatus(args.SelectedDevice, "The app is not exist in the device.", DevicePickerDisplayStatusOptions.ShowRetryButton);
                }
                else
                {
                    // 請求送出參數到遠端設備的 App
                    DialAppLaunchResult result = await app.RequestLaunchAsync("Test");

                    if (result == DialAppLaunchResult.Launched)
                    {
                        activeDevice = args.SelectedDevice;
                        sender.SetDisplayStatus(args.SelectedDevice, "connected", DevicePickerDisplayStatusOptions.ShowDisconnectButton);
                        sender.Hide();
                    }
                    else
                    {
                        sender.SetDisplayStatus(args.SelectedDevice, "Device Error", DevicePickerDisplayStatusOptions.ShowRetryButton);
                    }
                }
            }
            catch (Exception ex)
            {
                sender.SetDisplayStatus(args.SelectedDevice, ex.Message, DevicePickerDisplayStatusOptions.None);
            }
        }
        private async void Picker_DisconnectButtonClicked(DevicePicker sender, DeviceDisconnectButtonClickedEventArgs args)
        {
            //Casting must occur from the UI thread.  This dispatches the casting calls to the UI thread.
            await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () =>
            {
                rootPage.NotifyUser("Disconnect Button clicked", NotifyType.StatusMessage);
                //Update the display status for the selected device.
                sender.SetDisplayStatus(args.Device, "Disconnecting", DevicePickerDisplayStatusOptions.ShowProgress);

                if (this.pvb.ProjectedPage != null)
                {
                    this.pvb.ProjectedPage.StopProjecting();
                }

                //Update the display status for the selected device.
                sender.SetDisplayStatus(args.Device, "Disconnected", DevicePickerDisplayStatusOptions.None);
                rootPage.NotifyUser("Disconnected", NotifyType.StatusMessage);

                // Set the active device variables to null
                activeDevice = null;
            });
        }
        private async Task StopProjection(DevicePicker sender, DeviceInformation device)
        {
            // 關閉新建立的 view
            projectionInstance.Content.StopProjection();

            //Update the display status for the selected device.
            sender.SetDisplayStatus(device, "Disconnecting", DevicePickerDisplayStatusOptions.ShowProgress);

            //Update the display status for the selected device.
            sender.SetDisplayStatus(device, "Disconnected", DevicePickerDisplayStatusOptions.None);

            // Set the active device variables to null
            activeDevice = null;
        }
        private async void Picker_DeviceSelected(DevicePicker sender, DeviceSelectedEventArgs args)
        {
            //Casting must occur from the UI thread.  This dispatches the casting calls to the UI thread.
            await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, async() =>
            {
                try
                {
                    // Set status to Connecting
                    picker.SetDisplayStatus(args.SelectedDevice, "Connecting", DevicePickerDisplayStatusOptions.ShowProgress);

                    // Getting the selected device improves debugging
                    DeviceInformation selectedDevice = args.SelectedDevice;

                    thisViewId = Windows.UI.ViewManagement.ApplicationView.GetForCurrentView().Id;

                    // If projection is already in progress, then it could be shown on the monitor again
                    // Otherwise, we need to create a new view to show the presentation
                    if (rootPage.ProjectionViewPageControl == null)
                    {
                        // First, create a new, blank view
                        var thisDispatcher = Window.Current.Dispatcher;
                        await CoreApplication.CreateNewView().Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
                        {
                            // ViewLifetimeControl is a wrapper to make sure the view is closed only
                            // when the app is done with it
                            rootPage.ProjectionViewPageControl = ViewLifetimeControl.CreateForCurrentView();

                            // Assemble some data necessary for the new page
                            pvb.MainPageDispatcher        = thisDispatcher;
                            pvb.ProjectionViewPageControl = rootPage.ProjectionViewPageControl;
                            pvb.MainViewId = thisViewId;

                            // Display the page in the view. Note that the view will not become visible
                            // until "StartProjectingAsync" is called
                            var rootFrame = new Frame();
                            rootFrame.Navigate(typeof(ProjectionViewPage), pvb);
                            Window.Current.Content = rootFrame;

                            Window.Current.Activate();
                        });
                    }

                    try
                    {
                        // Start/StopViewInUse are used to signal that the app is interacting with the
                        // view, so it shouldn't be closed yet, even if the user loses access to it
                        rootPage.ProjectionViewPageControl.StartViewInUse();

                        try
                        {
                            await ProjectionManager.StartProjectingAsync(rootPage.ProjectionViewPageControl.Id, thisViewId, selectedDevice);
                        }
                        catch (Exception ex)
                        {
                            if (!ProjectionManager.ProjectionDisplayAvailable || pvb.ProjectedPage == null)
                            {
                                throw ex;
                            }
                        }

                        // ProjectionManager currently can throw an exception even when projection has started.\
                        // Re-throw the exception when projection has not been started after calling StartProjectingAsync
                        if (ProjectionManager.ProjectionDisplayAvailable && pvb.ProjectedPage != null)
                        {
                            this.player.Pause();
                            await pvb.ProjectedPage.SetMediaSource(this.player.Source, this.player.Position);
                            activeDevice = selectedDevice;
                            // Set status to Connected
                            picker.SetDisplayStatus(args.SelectedDevice, "Connected", DevicePickerDisplayStatusOptions.ShowDisconnectButton);
                            picker.Hide();
                        }
                        else
                        {
                            rootPage.NotifyUser(string.Format("Projection has failed to '{0}'", selectedDevice.Name), NotifyType.ErrorMessage);
                            // Set status to Failed
                            picker.SetDisplayStatus(args.SelectedDevice, "Connection Failed", DevicePickerDisplayStatusOptions.ShowRetryButton);
                        }
                    }
                    catch (Exception)
                    {
                        rootPage.NotifyUser(string.Format("Projection has failed to '{0}'", selectedDevice.Name), NotifyType.ErrorMessage);
                        // Set status to Failed
                        try { picker.SetDisplayStatus(args.SelectedDevice, "Connection Failed", DevicePickerDisplayStatusOptions.ShowRetryButton); } catch { }
                    }
                }
                catch (Exception ex)
                {
                    UnhandledExceptionPage.ShowUnhandledException(ex);
                }
            });
        }
        private async void Picker_DisconnectButtonClicked(DevicePicker sender, DeviceDisconnectButtonClickedEventArgs args)
        {
            //Casting must occur from the UI thread.  This dispatches the casting calls to the UI thread.
            await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, async () =>
            {
                rootPage.NotifyUser("Disconnect Button clicked", NotifyType.StatusMessage);

                //Update the display status for the selected device.
                sender.SetDisplayStatus(args.Device, "Disconnecting", DevicePickerDisplayStatusOptions.ShowProgress);

                bool disconnected = false;
                if (this.activeCastConnectionHandler is ProjectionViewBroker)
                    disconnected = TryStopProjectionManagerAsync((ProjectionViewBroker)activeCastConnectionHandler);
                if (this.activeCastConnectionHandler is DialApp)
                    disconnected = await TryStopDialAppAsync((DialApp)activeCastConnectionHandler);
                if (this.activeCastConnectionHandler is CastingConnection)
                    disconnected = await TryDisconnectCastingSessionAsync((CastingConnection)activeCastConnectionHandler);

                if (disconnected)
                {
                    //Update the display status for the selected device.
                    try { sender.SetDisplayStatus(args.Device, "Disconnected", DevicePickerDisplayStatusOptions.None); } catch { }
                    // Set the active device variables to null
                    activeDevice = null;
                    activeCastConnectionHandler = null;

                    //Hide the picker
                    sender.Hide();
                }
                else
                {
                    //Update the display status for the selected device.
                    sender.SetDisplayStatus(args.Device, "Disconnect failed", DevicePickerDisplayStatusOptions.ShowDisconnectButton);
                }
            });
        }
        private async void Picker_DisconnectButtonClicked(DevicePicker sender, DeviceDisconnectButtonClickedEventArgs args)
        {
            //Casting must occur from the UI thread.  This dispatches the casting calls to the UI thread.
            await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () =>
            {
                rootPage.NotifyUser("Disconnect Button clicked", NotifyType.StatusMessage);
                //Update the display status for the selected device.
                sender.SetDisplayStatus(args.Device, "Disconnecting", DevicePickerDisplayStatusOptions.ShowProgress);

                if (this.pvb.ProjectedPage != null)
                    this.pvb.ProjectedPage.StopProjecting();

                //Update the display status for the selected device.
                sender.SetDisplayStatus(args.Device, "Disconnected", DevicePickerDisplayStatusOptions.None);
                rootPage.NotifyUser("Disconnected", NotifyType.StatusMessage);

                // Set the active device variables to null
                activeDevice = null;
            });
        }
        private async void DevicePicker_DisconnectButtonClicked(DevicePicker sender, DeviceDisconnectButtonClickedEventArgs args)
        {
            await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () =>
            {
                // 關閉新建立的 view
                projectionInstance.Content.StopProjection();

                //Update the display status for the selected device.
                sender.SetDisplayStatus(args.Device, "Disconnecting", DevicePickerDisplayStatusOptions.ShowProgress);

                //Update the display status for the selected device.
                sender.SetDisplayStatus(args.Device, "Disconnected", DevicePickerDisplayStatusOptions.None);

                // Set the active device variables to null
                activeDevice = null;
            });
        }
        private async Task ProjectioinViewToScreen(DevicePicker sender, DeviceSelectedEventArgs args)
        {
            // 更新 picker 上設備的 status
            sender.SetDisplayStatus(args.SelectedDevice, "Connecting", DevicePickerDisplayStatusOptions.ShowProgress);

            // 取得目前選到設備的資訊
            activeDevice = args.SelectedDevice;

            // 現在 view 的 Id 與 CoreDispatcher
            int currentViewId = ApplicationView.GetForCurrentView().Id;
            CoreDispatcher currentDispatcher = Window.Current.Dispatcher;

            // 建立新的 view,
            if (projectionInstance.ProjectionViewPageControl == null)
            {
                await CoreApplication.CreateNewView().Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
                {
                    // 建立新 viewe 的生命管理器
                    projectionInstance.ProjectionViewPageControl = ViewLifetimeControl.CreateForCurrentView();
                    projectionInstance.MainViewId = currentViewId;

                    var rootFrame = new Frame();
                    rootFrame.Navigate(typeof(ProjectionPage), projectionInstance);

                    // 這裏的 Window 代表是新建立這個 view 的 Window
                    // 但是要等到呼叫 ProjectionManager.StartProjectingAsync 才會顯示
                    Window.Current.Content = rootFrame;
                    Window.Current.Activate();
                });
            }

            // 直接切換到指定的 view id
            //bool viewShown = await ApplicationViewSwitcher.TryShowAsStandaloneAsync(projectionInstance.ProjectionViewPageControl.Id);

            // 通知要使用新的 view
            projectionInstance.ProjectionViewPageControl.StartViewInUse();
            await ProjectionManager.SwapDisplaysForViewsAsync(projectionInstance.ProjectionViewPageControl.Id, currentViewId);
            try
            {
                await ProjectionManager.StartProjectingAsync(projectionInstance.ProjectionViewPageControl.Id, currentViewId, activeDevice);

                player.Pause();

                sender.SetDisplayStatus(args.SelectedDevice, "connected", DevicePickerDisplayStatusOptions.ShowDisconnectButton);
            }
            catch (Exception ex)
            {
                sender.SetDisplayStatus(args.SelectedDevice, ex.Message, DevicePickerDisplayStatusOptions.ShowRetryButton);
                if (ProjectionManager.ProjectionDisplayAvailable == false)
                {
                    throw;
                }
            }
        }
        private async Task StopDialConnection(DevicePicker picker, DeviceInformation device)
        {
            try
            {
                // 取得被選擇的 dial device
                DialDevice selectedDialDevice = await DialDevice.FromIdAsync(device.Id);
                // 更新 picker status
                picker.SetDisplayStatus(device, "connecting", DevicePickerDisplayStatusOptions.ShowProgress);
                // 取得 dial app 
                DialApp app = selectedDialDevice.GetDialApp("castingsample");

                // 請求斷綫
                DialAppStopResult result = await app.StopAsync();

                if (result == DialAppStopResult.Stopped)
                {
                    picker.SetDisplayStatus(device, "Disconnected", DevicePickerDisplayStatusOptions.None);
                    activeDevice = null;
                    picker.Hide();
                }
                else
                {
                    if (result == DialAppStopResult.StopFailed || result == DialAppStopResult.NetworkFailure)
                    {
                        // 如果失敗的話要記得多 retry 的機制
                        picker.SetDisplayStatus(device, "Error", DevicePickerDisplayStatusOptions.ShowDisconnectButton);
                    }
                    else
                    {
                        // 如果設備沒有支援 Stop 機制,則直接清楚連綫就好
                        activeDevice = null;
                    }
                }
            }
            catch (Exception ex)
            {
            }
        }
        private async Task SendDialParameter(DevicePicker sender, DeviceSelectedEventArgs args)
        {
            try
            {
                // 設定遠端設備現在要準備連綫
                sender.SetDisplayStatus(args.SelectedDevice, "connecting", DevicePickerDisplayStatusOptions.ShowProgress);

                // 取得遠端設備中支援指定 app name 的 App              
                DialDevice dialDevice = await DialDevice.FromIdAsync(args.SelectedDevice.Id);
                DialApp app = dialDevice.GetDialApp("castingsample");

                if (app == null)
                {
                    // 嘗試建立 DIAL device,如果失敗代表那個設備不支援 DIAL
                    sender.SetDisplayStatus(args.SelectedDevice, "The app is not exist in the device.", DevicePickerDisplayStatusOptions.ShowRetryButton);
                }
                else
                {
                    // 請求送出參數到遠端設備的 App 
                    DialAppLaunchResult result = await app.RequestLaunchAsync("Test");

                    if (result == DialAppLaunchResult.Launched)
                    {
                        activeDevice = args.SelectedDevice;
                        sender.SetDisplayStatus(args.SelectedDevice, "connected", DevicePickerDisplayStatusOptions.ShowDisconnectButton);
                        sender.Hide();
                    }
                    else
                    {
                        sender.SetDisplayStatus(args.SelectedDevice, "Device Error", DevicePickerDisplayStatusOptions.ShowRetryButton);
                    }
                }
            }
            catch (Exception ex)
            {
                sender.SetDisplayStatus(args.SelectedDevice, ex.Message, DevicePickerDisplayStatusOptions.None);
            }
        }