背水一战 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 = ;
// 当前 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 = ; 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 = ;
bool releasedCopy = false; lock (this)
{
releasedCopy = _released;
if (!_released)
{
refCountCopy = --_refCount;
if (refCountCopy == )
{
// 当前 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 == )
{
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
[源码下载]
背水一战 Windows 10 (4) - UI: 多窗口的更多相关文章
- 背水一战 Windows 10 (3) - UI: 窗口全屏, 窗口尺寸
[源码下载] 背水一战 Windows 10 (3) - UI: 窗口全屏, 窗口尺寸 作者:webabcd 介绍背水一战 Windows 10 之 UI 窗口全屏 窗口尺寸 示例1.窗口全屏UI/F ...
- 背水一战 Windows 10 (5) - UI: 标题栏
[源码下载] 背水一战 Windows 10 (5) - UI: 标题栏 作者:webabcd 介绍背水一战 Windows 10 之 UI 标题栏 示例TitleBarDemo.xaml <P ...
- 背水一战 Windows 10 (2) - UI: 概述, 启动屏幕, 屏幕方向
[源码下载] 背水一战 Windows 10 (2) - UI: 概述, 启动屏幕, 屏幕方向 作者:webabcd 介绍背水一战 Windows 10 之 UI UI 设计概述 启动屏幕(闪屏) 屏 ...
- 背水一战 Windows 10 (8) - 控件 UI: StateTrigger
[源码下载] 背水一战 Windows 10 (8) - 控件 UI: StateTrigger 作者:webabcd 介绍背水一战 Windows 10 之 控件 UI VisualState 之 ...
- 背水一战 Windows 10 (7) - 控件 UI: VisualState, VisualStateManager, 控件的默认 UI
[源码下载] 背水一战 Windows 10 (7) - 控件 UI: VisualState, VisualStateManager, 控件的默认 UI 作者:webabcd 介绍背水一战 Wind ...
- 背水一战 Windows 10 (6) - 控件 UI: 字体的自动继承的特性, Style, ControlTemplate
[源码下载] 背水一战 Windows 10 (6) - 控件 UI: 字体的自动继承的特性, Style, ControlTemplate 作者:webabcd 介绍背水一战 Windows 10 ...
- 背水一战 Windows 10 (36) - 控件(弹出类): ToolTip, Popup, PopupMenu
[源码下载] 背水一战 Windows 10 (36) - 控件(弹出类): ToolTip, Popup, PopupMenu 作者:webabcd 介绍背水一战 Windows 10 之 控件(弹 ...
- 背水一战 Windows 10 (28) - 控件(文本类): TextBox, PasswordBox
[源码下载] 背水一战 Windows 10 (28) - 控件(文本类): TextBox, PasswordBox 作者:webabcd 介绍背水一战 Windows 10 之 控件(文本类) T ...
- 背水一战 Windows 10 (26) - XAML: x:DeferLoadStrategy, x:Null
[源码下载] 背水一战 Windows 10 (26) - XAML: x:DeferLoadStrategy, x:Null 作者:webabcd 介绍背水一战 Windows 10 之 XAML ...
随机推荐
- Java程序员的日常 —— Java类加载中的顺序
之前说过Java中类的加载顺序,这次看完继承部分,就结合继承再来说说类的加载顺序. 继承的加载顺序 由于static块会在首次加载类的时候执行,因此下面的例子就是用static块来测试类的加载顺序. ...
- win2008 强制删除故障集群配置
在正常删除Cluster 节点之后,再添加节点时,报“节点已经加入群集”,无法加入,注册表信息删除后可正常移除Cluster服务,如下: win2008故障转移群集无法退出节点时 删除注册表中这两个后 ...
- 用scrollTop制作一个自动滚动公告栏
我们在浏览网页时,经常会看到会一些滚动的栏目,比如向上滚动的公告.新闻等.其实他们的制作都不难,只要学了基础的html.css.javascript就可以做出来,用JavaScript的scrollT ...
- Mybatis中SqlMapper配置的扩展与应用(1)
奋斗了好几个晚上调试程序,写了好几篇博客,终于建立起了Mybatis配置的扩展机制.虽然扩展机制是重要的,然而如果没有真正实用的扩展功能,那也至少是不那么鼓舞人心的,这篇博客就来举几个扩展的例子. 这 ...
- zabbix 3.0 安装 ubuntu环境
zabbix 3.0 安装 标签(空格分隔): 开发 [TOC] 下载deb # wget http://repo.zabbix.com/zabbix/3.0/ubuntu/pool/main/z/z ...
- JSON学习之一
1.JSON:JavaScript Object Notation(javaScript对象表示法),JSON是存储和交换文本信息的语法,类似XML:JSON比XML更小,更快,更易解析: { &qu ...
- 直接修改.NET程序集 LLBL Gen 2.x-4.x 许可授权方法研究
做数据库开发,如果要用ORM,LLBL Gen是一款优秀的框架和工具,目前最新版本是4.0.同时也推出了Lite免费版本,与Visual Studio的Express版本一样, 免费,但是它仅仅只支持 ...
- 利用Microsoft.Office.Interop.Excel 将web页面转成PDF
网上有很多将Web页面转成PDF的方法,还有许多收费的第三方插件.其实利用Office 自带的将EXCEL发布成PDF的功能就可以实现,如果你的需求没有多复杂,可以采用笔者的方法. 首先将web页面h ...
- java线程(2)--同步和锁
参考转载:http://rainyear.iteye.com/blog/1734311 http://turandot.iteye.com/blog/1704027 http://www.cnblog ...
- Elasticsearch聚合 之 Date Histogram聚合
Elasticsearch的聚合主要分成两大类:metric和bucket,2.0中新增了pipeline还没有研究.本篇还是来介绍Bucket聚合中的常用聚合--date histogram.参考: ...