背水一戰 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
  • 示例項目結構 在 Visual Studio 中創建一個 WinForms 應用程式後,項目結構如下所示: MyWinFormsApp/ │ ├───Properties/ │ └───Settings.settings │ ├───bin/ │ ├───Debug/ │ └───Release/ ...
  • [STAThread] 特性用於需要與 COM 組件交互的應用程式,尤其是依賴單線程模型(如 Windows Forms 應用程式)的組件。在 STA 模式下,線程擁有自己的消息迴圈,這對於處理用戶界面和某些 COM 組件是必要的。 [STAThread] static void Main(stri ...
  • 在WinForm中使用全局異常捕獲處理 在WinForm應用程式中,全局異常捕獲是確保程式穩定性的關鍵。通過在Program類的Main方法中設置全局異常處理,可以有效地捕獲並處理未預見的異常,從而避免程式崩潰。 註冊全局異常事件 [STAThread] static void Main() { / ...
  • 前言 給大家推薦一款開源的 Winform 控制項庫,可以幫助我們開發更加美觀、漂亮的 WinForm 界面。 項目介紹 SunnyUI.NET 是一個基於 .NET Framework 4.0+、.NET 6、.NET 7 和 .NET 8 的 WinForm 開源控制項庫,同時也提供了工具類庫、擴展 ...
  • 說明 該文章是屬於OverallAuth2.0系列文章,每周更新一篇該系列文章(從0到1完成系統開發)。 該系統文章,我會儘量說的非常詳細,做到不管新手、老手都能看懂。 說明:OverallAuth2.0 是一個簡單、易懂、功能強大的許可權+可視化流程管理系統。 有興趣的朋友,請關註我吧(*^▽^*) ...
  • 一、下載安裝 1.下載git 必須先下載並安裝git,再TortoiseGit下載安裝 git安裝參考教程:https://blog.csdn.net/mukes/article/details/115693833 2.TortoiseGit下載與安裝 TortoiseGit,Git客戶端,32/6 ...
  • 前言 在項目開發過程中,理解數據結構和演算法如同掌握蓋房子的秘訣。演算法不僅能幫助我們編寫高效、優質的代碼,還能解決項目中遇到的各種難題。 給大家推薦一個支持C#的開源免費、新手友好的數據結構與演算法入門教程:Hello演算法。 項目介紹 《Hello Algo》是一本開源免費、新手友好的數據結構與演算法入門 ...
  • 1.生成單個Proto.bat內容 @rem Copyright 2016, Google Inc. @rem All rights reserved. @rem @rem Redistribution and use in source and binary forms, with or with ...
  • 一:背景 1. 講故事 前段時間有位朋友找到我,說他的窗體程式在客戶這邊出現了卡死,讓我幫忙看下怎麼回事?dump也生成了,既然有dump了那就上 windbg 分析吧。 二:WinDbg 分析 1. 為什麼會卡死 窗體程式的卡死,入口門檻很低,後續往下分析就不一定了,不管怎麼說先用 !clrsta ...
  • 前言 人工智慧時代,人臉識別技術已成為安全驗證、身份識別和用戶交互的關鍵工具。 給大家推薦一款.NET 開源提供了強大的人臉識別 API,工具不僅易於集成,還具備高效處理能力。 本文將介紹一款如何利用這些API,為我們的項目添加智能識別的亮點。 項目介紹 GitHub 上擁有 1.2k 星標的 C# ...