[源碼下載] 背水一戰 Windows 10 (4) - UI: 多視窗 作者:webabcd介紹背水一戰 Windows 10 之 UI 多視窗 示例1、自定義幫助類,用於簡化 SecondaryView 的管理UI/MultipleViews/SecondaryViewHelper.cs 2、擴 ...
背水一戰 Windows 10 (4) - UI: 多視窗
作者:webabcd
介紹
背水一戰 Windows 10 之 UI
- 多視窗
示例
1、自定義幫助類,用於簡化 SecondaryView 的管理
UI/MultipleViews/SecondaryViewHelper.cs
/* * SecondaryViewHelper - 自定義的一個幫助類,用於簡化 SecondaryView 的管理 */ using System; using System.ComponentModel; using Windows.UI.Core; using Windows.UI.ViewManagement; namespace Windows10.UI.MultipleViews { public class SecondaryViewHelper : INotifyPropertyChanged { // for INotifyPropertyChanged public event PropertyChangedEventHandler PropertyChanged; // 當前 SecondaryView 的 CoreDispatcher private CoreDispatcher _dispatcher; // 當前 SecondaryView 的 ApplicationView private ApplicationView _applicationView; // 當前 SecondaryView 的標題 private string _title; // 當前 SecondaryView 的視窗標識 private int _viewId; // 當前 SecondaryView 被引用的次數 private int _refCount = 0; // 當前 SecondaryView 是否已經被釋放 private bool _released = false; // 禁止通過 new 實例化 private SecondaryViewHelper(CoreWindow newWindow) { _dispatcher = newWindow.Dispatcher; _viewId = ApplicationView.GetApplicationViewIdForWindow(newWindow); _applicationView = ApplicationView.GetForCurrentView(); RegisterForEvents(); } // 實例化 SecondaryViewHelper public static SecondaryViewHelper CreateForCurrentView() { /* * CoreWindow.GetForCurrentThread() - 獲取當前視窗的 CoreWindow */ return new SecondaryViewHelper(CoreWindow.GetForCurrentThread()); } private void RegisterForEvents() { /* * ApplicationView.GetForCurrentView() - 獲取當前視窗的 ApplicationView * ApplicationView.Consolidated - 當前 app 存活著兩個或兩個以上的視窗時,此視窗關閉後觸發的事件 */ ApplicationView.GetForCurrentView().Consolidated += SecondaryViewHelper_Consolidated; } private void UnregisterForEvents() { ApplicationView.GetForCurrentView().Consolidated -= SecondaryViewHelper_Consolidated; } private void SecondaryViewHelper_Consolidated(ApplicationView sender, ApplicationViewConsolidatedEventArgs args) { StopViewInUse(); } // 當前 SecondaryView 開始使用了(與 StopViewInUse() 成對) // 因為每一個視窗都可以被同 app 的別的視窗調用,而每一個視窗又都是一個獨立的線程,所以要做好線程處理 public int StartViewInUse() { bool releasedCopy = false; int refCountCopy = 0; lock (this) { releasedCopy =_released; if (!_released) { refCountCopy = ++_refCount; } } if (releasedCopy) { throw new InvalidOperationException("this view is being disposed"); } return refCountCopy; } // 當前 SecondaryView 結束使用了(與 StartViewInUse() 成對) // 因為每一個視窗都可以被同 app 的別的視窗調用,而每一個視窗又都是一個獨立的線程,所以要做好線程處理 public int StopViewInUse() { int refCountCopy = 0; bool releasedCopy = false; lock (this) { releasedCopy = _released; if (!_released) { refCountCopy = --_refCount; if (refCountCopy == 0) { // 當前 SecondaryView 不再被任何人需要了,清理之 var task = _dispatcher.RunAsync(CoreDispatcherPriority.Low, FinalizeRelease); } } } if (releasedCopy) { throw new InvalidOperationException("this view is being disposed"); } return refCountCopy; } // 清理當前 SecondaryView private void FinalizeRelease() { bool justReleased = false; lock (this) { if (_refCount == 0) { justReleased = true; _released = true; } } if (justReleased) { UnregisterForEvents(); // 觸發 Released 事件 OnReleased(EventArgs.Empty); } } // 定義 Released 事件 public event EventHandler<EventArgs> Released; protected virtual void OnReleased(EventArgs e) { EventHandler<EventArgs> handler = Released; if (handler != null) handler(this, e); } public int Id { get { return _viewId; } } public string Title { get { return _title; } set { if (_title != value) { _title = value; if (PropertyChanged != null) { PropertyChanged(this, new PropertyChangedEventArgs(nameof(Title))); } } } } public bool IsReleased { get { return _released; } } public ApplicationView ApplicationView { get { return _applicationView; } } } }
2、擴展 Application 對象,定義一些需要用到的全局變數
UI/MultipleViews/AppPartial.cs
/* * 擴展 Application 對象,定義一些需要用到的全局變數 */ using Windows.ApplicationModel.Activation; using Windows.UI.Core; using Windows.UI.ViewManagement; using Windows.UI.Xaml; using Windows.UI.Xaml.Controls; namespace Windows10 { public partial class App { // PrimaryView 的 CoreDispatcher private CoreDispatcher _mainDispatcher; // PrimaryView 的視窗標識 private int _mainViewId; // partial method,實現了 App.xaml.cs 中的聲明 partial void OnLaunched_MultipleViews(LaunchActivatedEventArgs args) { _mainDispatcher = Window.Current.Dispatcher; _mainViewId = ApplicationView.GetForCurrentView().Id; } public CoreDispatcher MainDispatcher { get { return _mainDispatcher; } } public int MainViewId { get { return _mainViewId; } } } }
3、用於演示 SecondaryView 的示例
UI/MultipleViews/SecondaryViewPage.xaml
<Page x:Class="Windows10.UI.MultipleViews.SecondaryViewPage" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="using:Windows10.UI.MultipleViews" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d"> <Grid Background="Transparent"> <StackPanel Margin="10 0 10 10"> <TextBlock Name="lblMsg" Margin="0 10 0 0" /> <Button Name="btnGoToMain" Content="切換到主視窗" Click="btnGoToMain_Click" Margin="0 10 0 0" /> <Button Name="btnGoToMainAndHideThisView" Content="切換到主視窗,並關閉此視窗" Click="btnGoToMainAndHideThisView_Click" Margin="0 10 0 0" /> </StackPanel> </Grid> </Page>
UI/MultipleViews/SecondaryViewPage.xaml.cs
/* * 演示“多視窗”相關知識點。本頁是 SecondaryView */ using System; using System.ComponentModel; using Windows.ApplicationModel.Core; using Windows.UI.Core; using Windows.UI.ViewManagement; using Windows.UI.Xaml; using Windows.UI.Xaml.Controls; using Windows.UI.Xaml.Navigation; namespace Windows10.UI.MultipleViews { public sealed partial class SecondaryViewPage : Page { private SecondaryViewHelper _secondaryViewHelper; public SecondaryViewPage() { this.InitializeComponent(); } protected override void OnNavigatedTo(NavigationEventArgs e) { _secondaryViewHelper = (SecondaryViewHelper)e.Parameter; _secondaryViewHelper.Released += _secondaryViewHelper_Released; // 設置當前視窗的 Title ApplicationView.GetForCurrentView().Title = _secondaryViewHelper.Title; _secondaryViewHelper.PropertyChanged += _secondaryViewHelper_PropertyChanged; } private void _secondaryViewHelper_PropertyChanged(object sender, PropertyChangedEventArgs e) { if (e.PropertyName == nameof(_secondaryViewHelper.Title)) { _secondaryViewHelper.ApplicationView.Title = _secondaryViewHelper.Title; } } private async void _secondaryViewHelper_Released(object sender, EventArgs e) { ((SecondaryViewHelper)sender).Released -= _secondaryViewHelper_Released; await ((App)App.Current).MainDispatcher.RunAsync(CoreDispatcherPriority.Normal, () => { // 調用主視窗線程,執行邏輯 }); Window.Current.Close(); } private async void btnGoToMain_Click(object sender, RoutedEventArgs e) { _secondaryViewHelper.StartViewInUse(); /* * ApplicationViewSwitcher.SwitchAsync() - 切換到指定的視窗 */ await ApplicationViewSwitcher.SwitchAsync ( ((App)App.Current).MainViewId // 準備顯示的視窗的 id ); _secondaryViewHelper.StopViewInUse(); } private async void btnGoToMainAndHideThisView_Click(object sender, RoutedEventArgs e) { _secondaryViewHelper.StartViewInUse(); /* * ApplicationViewSwitcher.SwitchAsync() - 切換到指定的視窗 */ await ApplicationViewSwitcher.SwitchAsync ( ((App)App.Current).MainViewId, // 準備顯示的視窗的 id ApplicationView.GetForCurrentView().Id, // 調用者的視窗 id ApplicationViewSwitchingOptions.ConsolidateViews // 切換行為選項(Default - 標準動畫切換; SkipAnimation - 不使用動畫切換; ConsolidateViews - 切換後關閉調用者視窗) ); _secondaryViewHelper.StopViewInUse(); } } }
4、用於演示 PrimaryView 的示例
UI/MultipleViews/Demo.xaml
<Page x:Class="Windows10.UI.MultipleViews.Demo" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="using:Windows10.UI.MultipleViews" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d"> <Grid Background="Transparent"> <StackPanel Margin="10 0 10 10"> <TextBlock Name="lblMsg" Margin="0 10 0 0" /> <Button Name="btnShow" Content="創建並顯示一個新的視窗" Click="btnShow_Click" Margin="0 10 0 0" /> <Button Name="btnChangeLastSecondaryViewTitle" Content="修改最近一個被我打開的 SecondaryView 的 Title" Click="btnChangeLastSecondaryViewTitle_Click" Margin="0 10 0 0" /> </StackPanel> </Grid> </Page>
UI/MultipleViews/Demo.xaml.cs
/* * 演示“多視窗”相關知識點。本頁是 PrimaryView * * * 解釋一下本例中用於說明的幾個名詞:PrimaryView - 主視窗; SecondaryView - 新開視窗 */ using System; using Windows.ApplicationModel.Core; using Windows.UI.Core; using Windows.UI.ViewManagement; using Windows.UI.Xaml; using Windows.UI.Xaml.Controls; namespace Windows10.UI.MultipleViews { public sealed partial class Demo : Page { // 自定義的用於簡化 SecondaryView 管理的幫助類 SecondaryViewHelper _secondaryViewHelper = null; public Demo() { this.InitializeComponent(); this.Loaded += Demo_Loaded; } private void Demo_Loaded(object sender, RoutedEventArgs e) { ApplicationView.PreferredLaunchWindowingMode = ApplicationViewWindowingMode.Auto; } private async void btnShow_Click(object sender, RoutedEventArgs e) { /* * CoreApplication.CreateNewView() - 創建一個新的 SecondaryView(只是新建一個 SecondaryView 實例,並不會顯示出來) */ await CoreApplication.CreateNewView().Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () => { _secondaryViewHelper = SecondaryViewHelper.CreateForCurrentView(); _secondaryViewHelper.Title = "i am secondary view"; _secondaryViewHelper.StartViewInUse(); var frame = new Frame(); frame.Navigate(typeof(SecondaryViewPage), _secondaryViewHelper); Window.Current.Content = frame; Window.Current.Activate(); // 這裡通過 ApplicationView.GetForCurrentView() 獲取到的是新開視窗的 ApplicationView 對象 ApplicationView secondaryView = ApplicationView.GetForCurrentView(); }); try { _secondaryViewHelper.StartViewInUse(); /* * ApplicationViewSwitcher.TryShowAsStandaloneAsync() - 在當前視窗的相鄰位置顯示另一個視窗 */ ApplicationViewSwitcher.DisableShowingMainViewOnActivation(); var viewShown = await ApplicationViewSwitcher.TryShowAsStandaloneAsync ( _secondaryViewHelper.Id, // 需要顯示的 SecondaryView 的視窗 id ViewSizePreference.Default, // 需要顯示的 SecondaryView 的尺寸首選項(經測試,此參數無效) ApplicationView.GetForCurrentView().Id, // 調用者的視窗 id ViewSizePreference.Default // 調用者的尺寸首選項(經測試,此參數無效) ); if (!viewShown) { lblMsg.Text = "顯示 SecondaryView 失敗"; } _secondaryViewHelper.StopViewInUse(); } catch (Exception ex) { lblMsg.Text = ex.ToString(); } } // 修改最近一個被我打開的 SecondaryView 的 Title private void btnChangeLastSecondaryViewTitle_Click(object sender, RoutedEventArgs e) { if (_secondaryViewHelper != null && !_secondaryViewHelper.IsReleased) _secondaryViewHelper.Title = new Random().Next().ToString(); } } }
OK
[源碼下載]