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

UI: 多窗口的更多相关文章

  1. 背水一战 Windows 10 (4) - UI: 多窗口

    [源码下载] 背水一战 Windows 10 (4) - UI: 多窗口 作者:webabcd 介绍背水一战 Windows 10 之 UI 多窗口 示例1.自定义帮助类,用于简化 Secondary ...

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

    https://code.msdn.microsoft.com/Layout-for-windows-that-ba648e1c/ https://msdn.microsoft.com/library ...

  3. 【Qt编程】Qt学习之窗口间的相互切换

    在用Qt设计GUI时,经常要设计两个窗口之间的相互切换,即可以从一个窗口跳转到另一个窗口,然后又从另一个窗口跳转回原窗口.下面我们来介绍具体的实现方法: 工程建立及功能描述: 首先,我们建立Qt  G ...

  4. c# winform 应用程序根据条件阻止窗口关闭

    //添加窗口关闭事件委托 在窗口关闭事件中处理 private void TestForm_FormClosing(object sender, FormClosingEventArgs e) { s ...

  5. Qt 使用QLabel、QMovie加载gif图片实现动态等待窗口

    新建基于Widget的应用程序,在ui的窗口中添加QLabel,对象名label,调整整个窗口大小. 准备loading.gif图片  Widget.cpp  12345678910111213141 ...

  6. 10、堆叠窗口StackedWidget

    新建项目,基类选择QMainWindow,勾选ui 堆叠窗口有三个page,每个page有个label   button处,快捷菜单,转到槽,添加代码 void MainWindow::on_push ...

  7. MFC单文档视图中嵌入GLFW窗口

    开始学习OpenGL由于有一段时间,但是glfw只有窗口区,虽然通过某种手段(移步这里)可以加入工具栏,但仍然无法作为一个标准的GUI,而直接在MFC或Qt里面使用OpenGL API感觉有诸多制肘, ...

  8. qt之串口

                                          qt串口讲解在QT中并没有特定的串口控制类,现在大部分人使用的是第三方写的qextserialport类,我们这里也使用这个 ...

  9. 【UGUI】Canvas和Rect Transform

    Canvas 1.所有的UI元件都需要放在Canvas里 2.UI元件的绘制顺序,与在 Hierarchy的顺序相同,在上面的元素会先被绘制,位于后续绘制元素的下面 3.可以选择3种不同的渲染模式: ...

随机推荐

  1. 如何提升代码编译的速度 iOS

    前阵子有遇到代码编译速度慢的问题,特别是在swift和object-c混编的过程中问题很突显. 网上找到一篇蛮好的文章里面又一些解决方法 推荐一下 http://www.open-open.com/l ...

  2. iOS Swift-简单值(The Swift Programming Language)

    iOS Swift-简单值(The Swift Programming Language) 常量的声明:let 在不指定类型的情况下声明的类型和所初始化的类型相同. //没有指定类型,但是初始化的值为 ...

  3. IOS 杂笔-16 (-(void)scrollViewDidEndScrollingAnimation:方法使用注意)

    今天在写项目的时候,遇到了一件令人抓狂的事情. 正如标题所示,被这个方法弄的团团转. -(void)scrollViewDidEndScrollingAnimation:是协议里的方法. 意味当动画结 ...

  4. JVM-加载,链接,初始化

    Java Virtual Machine 动态的加载,链接和初始化类和接口.那么,Class 二进制文件是怎样被 JVM 加载到内存中的?JVM 如何描述一个 Java 类?类或接口怎么才能让 JVM ...

  5. IO redirect

    在OS中,每启动一个进程,就自动的分配了三个流到进程中. [0:标准输入流,即键盘输入].[1:标准输出流,输出到显示器].[2:错误输出流,输出到显示器],其余的还未指定. 基本IO操作 cmd & ...

  6. W3School-CSS 内边距 (padding) 实例

    CSS 内边距 (padding) 实例 CSS 实例 CSS 背景实例 CSS 文本实例 CSS 字体(font)实例 CSS 边框(border)实例 CSS 外边距 (margin) 实例 CS ...

  7. ERROR! MySQL is running but PID file could not be found

    /etc/init.d/mysql status提示ERROR! MySQL is running but PID file could not be found先打印MYSQL进程ps aux | ...

  8. Android入门笔记(一)

    第一部分,Android开发环境的搭建 1.去http://www.oracle.com/technetwork/java/javase/downloads/index.html下载最新版本jdk并安 ...

  9. mysqld设置密码

    用root 进入mysql后 mysql>set password =password('你的密码'); mysql>flush privileges;   登录: mysql -u ro ...

  10. JS入门学习,写一个时钟~

    <!-- 耽搁了几天,于是又继续回到JS的学习了~~ 各种头大,加油吧... --> <!doctype html><html><head> <t ...