背水一戰 Windows 10 (4) - UI: 多視窗

来源:http://www.cnblogs.com/webabcd/archive/2016/03/25/5318129.html
-Advertisement-
Play Games

[源碼下載] 背水一戰 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
[源碼下載]


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 首先,在模型類中引用 System.ComponentModel.DataAnnotations 命名空間;System.ComponentModel.DataAnnotations 命名空間提供定義 ASP.NET MVC 和 ASP.NET 數據控制項的類的特性(即內置驗證屬性,你可以使用聲明的任 ...
  • 提供對查詢結果和查詢對資料庫的影響 此枚舉有一個 FlagsAttribute 屬性,通過該屬性可使其成員值按位組合。 命名空間: System.Data程式集: System.Data(在 System.Data.dll 中) 語法: Default:此查詢可能返回多個結果集。執行查詢可能會影響數 ...
  • 最近需要寫一個正則去匹配一個小數(小數非負,保留兩位),為方便和大家一塊兒學習研究,特意將我分析正則的過程寫下來。 第一,分析都會有哪些是合法的可以匹配的,以及非法的字元,先列舉下來。合法的有1、1.11、0.12、0.3、0、0.00,非法的可能會出現001、01.1、01.、-1、1.123等等 ...
  • 二維碼掃描的實現,簡單的來說可以分三步走:“成像”、“截圖”與“識別”。 UWP開發中,最常用的媒體工具非MediaCapture莫屬了,下麵就來簡單介紹一下如何利用MediaCapture來實現掃描和截圖並且利用Zxing識別二維碼,以及會遇到的問題和需要註意的地方。 1. 初始化與成像 1 pr ...
  • 我發現VS的一些異常情況,比如,會丟失一些信息,如:工程的位置信息,啟動信息。 和本問題相關的是,會丟失工程項目的依賴關係。(雖然,對工程的引用還在,但從屬性里來看,工程項目的引用關係已經丟失) 那麼問題就好解決了, 1,刪除引用的工程DLL 2,重新引用工程項目 3,重建解決方案 OK 下麵是一些 ...
  • 思路 定義幾個類: HealthCheckItem類:檢查項目 屬性: HealthCheckItem類中的方法: 主界面: HealthCheckSet類:體檢套餐 屬性: HealthCheckSet類中的方法: 獲取價格的方法: 添加新套餐: 載入套餐下拉框信息: 初始化檢查項目: 添加檢查項 ...
  • 相信.Net開發人員都想能夠熟記各種VS快捷鍵以提高平時開發的效率,但苦於記憶能力太差而快捷鍵又特別多,特別煩,所以作罷! 下麵我將簡單介紹一下我記憶VS快捷鍵的一些方法,希望對大家有所幫助。 1、視窗快捷鍵 (大家有沒有發現但凡跟視窗掛上鉤的快捷鍵當中都有一個W,那是因為W代表Windows也就是 ...
  • 一、前言 對於WebForm開發,請求通常是一個以.aspx結尾的url,對應一個物理文件,從代碼的角度來說它其實是一個控制項(Page)。而在MVC中,一個請求對應的是一個Controller里的Action。熟悉asp.net的朋友都知道,asp.net請求實際都是交給HttpHandler處理( ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...