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

UI: 多窗口的更多相关文章
- 背水一战 Windows 10 (4) - UI: 多窗口
[源码下载] 背水一战 Windows 10 (4) - UI: 多窗口 作者:webabcd 介绍背水一战 Windows 10 之 UI 多窗口 示例1.自定义帮助类,用于简化 Secondary ...
- Win10 UI入门窗口由默认500px to 320px
https://code.msdn.microsoft.com/Layout-for-windows-that-ba648e1c/ https://msdn.microsoft.com/library ...
- 【Qt编程】Qt学习之窗口间的相互切换
在用Qt设计GUI时,经常要设计两个窗口之间的相互切换,即可以从一个窗口跳转到另一个窗口,然后又从另一个窗口跳转回原窗口.下面我们来介绍具体的实现方法: 工程建立及功能描述: 首先,我们建立Qt G ...
- c# winform 应用程序根据条件阻止窗口关闭
//添加窗口关闭事件委托 在窗口关闭事件中处理 private void TestForm_FormClosing(object sender, FormClosingEventArgs e) { s ...
- Qt 使用QLabel、QMovie加载gif图片实现动态等待窗口
新建基于Widget的应用程序,在ui的窗口中添加QLabel,对象名label,调整整个窗口大小. 准备loading.gif图片 Widget.cpp 12345678910111213141 ...
- 10、堆叠窗口StackedWidget
新建项目,基类选择QMainWindow,勾选ui 堆叠窗口有三个page,每个page有个label button处,快捷菜单,转到槽,添加代码 void MainWindow::on_push ...
- MFC单文档视图中嵌入GLFW窗口
开始学习OpenGL由于有一段时间,但是glfw只有窗口区,虽然通过某种手段(移步这里)可以加入工具栏,但仍然无法作为一个标准的GUI,而直接在MFC或Qt里面使用OpenGL API感觉有诸多制肘, ...
- qt之串口
qt串口讲解在QT中并没有特定的串口控制类,现在大部分人使用的是第三方写的qextserialport类,我们这里也使用这个 ...
- 【UGUI】Canvas和Rect Transform
Canvas 1.所有的UI元件都需要放在Canvas里 2.UI元件的绘制顺序,与在 Hierarchy的顺序相同,在上面的元素会先被绘制,位于后续绘制元素的下面 3.可以选择3种不同的渲染模式: ...
随机推荐
- AsyncHttpClient 源码分析
上一篇文章从功能和用法上对AsyncHttpClient做了个大致介绍,今天我们和以往一样,从内部实现.原理的角度带领大家看看 其工作机制,以便加深理解.写程序越多,我发现每接触一个新东西,都会有强烈 ...
- Play Framework 完整实现一个APP(八)
创建Tag标签 1.创建Model @Entity @Table(name = "blog_tag") public class Tag extends Model impleme ...
- RMAN冷备份异机还原
1:环境准备 在新的服务器上安装ORACLE实例,安装过程中需要注意源服务器与目标服务器的ORACLE_SID一致,另外确保安装路径与源路径一致(不仅是安装目录,甚至包括数据文件.控制文件目录.联机重 ...
- ORA-19502: write error on file "xxxxx", block number xxxx
错误现象: 在ORACLE 10g下为表空间IGNITE_EGVSQL01增加数据文件时,报如下错误: SQL> ALTER TABLESPACE IGNITE_EGVSQL01 AD ...
- js获取浏览器内核、类型、版本以及系统类型
正则表达式: var rsys = /\b(windows|win32|macintosh|mac os x|adobeair|linux|unix)\b/; var rkn = /\b(opera| ...
- 曲演杂坛--当ROW_NUMBER遇到TOP
值班期间研发同事打来电话,说应用有超时,上服务器上检查发现有SQL大批量地执行,该SQL消耗IO资源较多,导致服务器存在IO瓶颈,细看SQL,发现自己都被整蒙了,不知道这SQL是要干啥,处理完问题赶紧 ...
- Mysql小技巧总汇
1.datetime类型字段格式化 SELECT DATE_FORMAT(date,'%Y-%m-%d %h:%m:%s') date FROM message; 结果: +------------- ...
- SQL Server DAC——专用管理员连接
今天打开数据库刚要连接时,看到“连接到服务器”窗口,突发的想到:要是SQL Server 不再响应正常的连接请求,又想使用数据库时,我们该怎么办? 其实我们还能通过“SQL Server D ...
- Ubuntu下Apache+SVN+submin实现WEB管理SVN
为什么需要submin管理SVN? 原来在Ubuntu下,都是直接通过命令行创建SVN仓库并分配权限,但是这有一些问题: 每创建一个SVN仓库,都需要修改httpd.conf 每创建一个帐户,都需要手 ...
- Centos7 and docker practices
1. Failed to get D-Bus connection: Operation not permitted error when you execute the systemctl star ...