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种不同的渲染模式: ...
随机推荐
- 如何提升代码编译的速度 iOS
前阵子有遇到代码编译速度慢的问题,特别是在swift和object-c混编的过程中问题很突显. 网上找到一篇蛮好的文章里面又一些解决方法 推荐一下 http://www.open-open.com/l ...
- iOS Swift-简单值(The Swift Programming Language)
iOS Swift-简单值(The Swift Programming Language) 常量的声明:let 在不指定类型的情况下声明的类型和所初始化的类型相同. //没有指定类型,但是初始化的值为 ...
- IOS 杂笔-16 (-(void)scrollViewDidEndScrollingAnimation:方法使用注意)
今天在写项目的时候,遇到了一件令人抓狂的事情. 正如标题所示,被这个方法弄的团团转. -(void)scrollViewDidEndScrollingAnimation:是协议里的方法. 意味当动画结 ...
- JVM-加载,链接,初始化
Java Virtual Machine 动态的加载,链接和初始化类和接口.那么,Class 二进制文件是怎样被 JVM 加载到内存中的?JVM 如何描述一个 Java 类?类或接口怎么才能让 JVM ...
- IO redirect
在OS中,每启动一个进程,就自动的分配了三个流到进程中. [0:标准输入流,即键盘输入].[1:标准输出流,输出到显示器].[2:错误输出流,输出到显示器],其余的还未指定. 基本IO操作 cmd & ...
- W3School-CSS 内边距 (padding) 实例
CSS 内边距 (padding) 实例 CSS 实例 CSS 背景实例 CSS 文本实例 CSS 字体(font)实例 CSS 边框(border)实例 CSS 外边距 (margin) 实例 CS ...
- 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 | ...
- Android入门笔记(一)
第一部分,Android开发环境的搭建 1.去http://www.oracle.com/technetwork/java/javase/downloads/index.html下载最新版本jdk并安 ...
- mysqld设置密码
用root 进入mysql后 mysql>set password =password('你的密码'); mysql>flush privileges; 登录: mysql -u ro ...
- JS入门学习,写一个时钟~
<!-- 耽搁了几天,于是又继续回到JS的学习了~~ 各种头大,加油吧... --> <!doctype html><html><head> <t ...