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();
        }
    }
}

时间: 2024-08-28 04:41:48

UI: 多窗口的相关文章

(二十七)unity4.6学习Ugui中文文档-------Unity3D UI (uGUI)窗口扩展

出处:http://blog.csdn.net/u010019717 下面是提供的例子: Unity3D UI (uGUI)窗口扩展 它是如何工作的? 也有官方的api文档: ?? ??

Win10 UI入门窗口由默认500px to 320px

https://code.msdn.microsoft.com/Layout-for-windows-that-ba648e1c/ https://msdn.microsoft.com/library/windows/apps/hh465371.aspx https://msdn.microsoft.com/zh-cn/library/windows/apps/hh465349.aspx http://scottge.net/2015/08/29/controlling-the-window-s

Android 布局学习之——Layout(布局)详解一

layout(布局)定义了用户界面的可视化结构(visual structure),如Activity的UI,应用窗口的UI. 有两种方式声明layout: 1.在xml文件中声明UI组件. 2.在运行时,实例化布局元素.我们可以以编码的方式创建View或ViewGroup对象,操纵它们的属性. 下面用一个小例子来学习怎样以编码的方式添加layout: 1 import android.app.Activity; 2 import android.graphics.Color; 3 import

中文Appium API 文档

该文档是Testerhome官方翻译的源地址:https://github.com/appium/appium/tree/master/docs/cn官方网站上的:http://appium.io/slate/cn/master/?ruby#about-appium 中文Appium API 文档 第一章:关于appium1.1 appium客户端客户端类库列表及Appium服务端支持 这些类库封装了标准Selenium客户端类库,为用户提供所有常见的JSON 格式selenium命令以及额外的

天道酬勤VIP输入法注入系列教程

目录: 教程目录:1.输入法注入-加载客户DLL2.输入法注入-UI类窗口注册3.输入法注入-伪造输入法文件4.输入法注入-还原每个导出函数5.输入法注入-输入法切换选择函数6.输入法注入-发送消息与消息处理7.输入法注入-完成伪造文件8.输入法注入-构建Hook模块主要功能9.输入法注入-Hook状态与4个自定义导出函数10.输入法注入-处理压缩A字符11.输入法注入-压缩字符串W宽窄转换 天道酬勤VIP输入法注入系列教程 下载地址 ziyuan.woyaoxueit.com

HOOK自绘原理 good

做“HOOK文件打开/保存对话框”的过程中,我首先研究了界面库的相关知识.界面库一般都是由C/C++这种中低级语言编码,这是因为在Windows下的界面库实现技术大都以直接操作控制Windows的消息和调用Windows的API为主,这就是这种中低级语言的优势了.无论何种界面库,最为根本的原理就是获得或者截获窗口的某些消息,按照自己的需要处理这些消息,画出自己需要的界面. 按照Windows下的界面库的使用方法来分类,可以分为两种: 1. 通过派生.继承界面库中的类来使用库.这类界面库现在是占绝

(转)VS2015的跨平台特性会对Qt带来冲击吗

VS2015的跨平台特性会对Qt带来冲击吗 原文来自:http://qiusuoge.com/13352.htmlvs2015支持c++开发跨平台的库,这样对于Qt而言会有多大的冲击呢?将来用VS开发c++跨平台和QT开发跨平台应用发展趋势各是怎样的?如果现在新项目要开发跨平台的高性能应用,如果用c++是选择QT还是VS2015的跨平台特性呢?另外VS2015跨平台对于界面的支持如何? 注意:不是在讨论IDE,也不是在讨论.net的跨平台!而是VS支持c++跨平台的特性.既然要跨平台,对于与系统

03、矢量图形查询工具(Symbol Unicode)

目前的软件开发中,很多地方都使用到了矢量图标,在 Metro app 的开发中,可以使用 Windows 系统图标(02.Universal app 中按钮图标使用 ),包括 Segoe UI Symbol.Segoe MDL2 Assets(Windows10 新添加). Segoe UI Emoji 等. 不过在开发中,遇到了一个问题,就是系统自带的 “字符映射表” 中很多图标太小了,又不能调整大小 ,不方便浏览,于是自己动手写了一个矢量图形的 Unicode 查询工具(使用 WPF 写的)

Qt中调用PolarSSL库(一)

最近一直在学习SSL相关的知识,也是先了解理论相关的知识,主要是SSL相关的基本概念和连接建立过程,主要是基于PolarSSL开源库进行学习.学习完了之后就希望能给有所运用,就想用Qt写一个简单的程序,增加对SSL相关概念的把握和对PolarSSL库的运用.当然,最终希望是可以使用Qt做一个比较完善的工具,帮助大家更好的理解和学习SSL相关知识.这都是后话,在第一篇里面,我们就简单用例子展示如何在Qt里面调用PolarSSL库. 这篇博客主要是讲解Qt里面调用PolarSSL库,至于SSL相关概