[源码下载]

背水一战 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: 多窗口的更多相关文章

  1. 背水一战 Windows 10 (3) - UI: 窗口全屏, 窗口尺寸

    [源码下载] 背水一战 Windows 10 (3) - UI: 窗口全屏, 窗口尺寸 作者:webabcd 介绍背水一战 Windows 10 之 UI 窗口全屏 窗口尺寸 示例1.窗口全屏UI/F ...

  2. 背水一战 Windows 10 (5) - UI: 标题栏

    [源码下载] 背水一战 Windows 10 (5) - UI: 标题栏 作者:webabcd 介绍背水一战 Windows 10 之 UI 标题栏 示例TitleBarDemo.xaml <P ...

  3. 背水一战 Windows 10 (2) - UI: 概述, 启动屏幕, 屏幕方向

    [源码下载] 背水一战 Windows 10 (2) - UI: 概述, 启动屏幕, 屏幕方向 作者:webabcd 介绍背水一战 Windows 10 之 UI UI 设计概述 启动屏幕(闪屏) 屏 ...

  4. 背水一战 Windows 10 (8) - 控件 UI: StateTrigger

    [源码下载] 背水一战 Windows 10 (8) - 控件 UI: StateTrigger 作者:webabcd 介绍背水一战 Windows 10 之 控件 UI VisualState 之 ...

  5. 背水一战 Windows 10 (7) - 控件 UI: VisualState, VisualStateManager, 控件的默认 UI

    [源码下载] 背水一战 Windows 10 (7) - 控件 UI: VisualState, VisualStateManager, 控件的默认 UI 作者:webabcd 介绍背水一战 Wind ...

  6. 背水一战 Windows 10 (6) - 控件 UI: 字体的自动继承的特性, Style, ControlTemplate

    [源码下载] 背水一战 Windows 10 (6) - 控件 UI: 字体的自动继承的特性, Style, ControlTemplate 作者:webabcd 介绍背水一战 Windows 10 ...

  7. 背水一战 Windows 10 (36) - 控件(弹出类): ToolTip, Popup, PopupMenu

    [源码下载] 背水一战 Windows 10 (36) - 控件(弹出类): ToolTip, Popup, PopupMenu 作者:webabcd 介绍背水一战 Windows 10 之 控件(弹 ...

  8. 背水一战 Windows 10 (28) - 控件(文本类): TextBox, PasswordBox

    [源码下载] 背水一战 Windows 10 (28) - 控件(文本类): TextBox, PasswordBox 作者:webabcd 介绍背水一战 Windows 10 之 控件(文本类) T ...

  9. 背水一战 Windows 10 (26) - XAML: x:DeferLoadStrategy, x:Null

    [源码下载] 背水一战 Windows 10 (26) - XAML: x:DeferLoadStrategy, x:Null 作者:webabcd 介绍背水一战 Windows 10 之 XAML ...

随机推荐

  1. IOS Socket 02-Socket基础知识

    1. 简介 Socket就是为网络服务提供的一种机制 通信的两端都是Socket 网络通信其实就是Socket间的通信 数据在两个Socket间通过IO传输 2. Socket通信流程图 3. 模拟Q ...

  2. .NetCore~Linux环境下部署

    NetCore正式版已经出现有段时候了,Windows下使用vs2015开发.netCore应用程序,然后通过dotnet程序开启WEB服务,用着很像node.js,当然我们不会于只局限于window ...

  3. fir.im Weekly - 不能错过的 GitHub Top 100 开源库

    好的工具&资源,会带来更多的灵感.本期 fir.im Weekly 精选了一些实用的 iOS,Android 的使用工具和源码分享,还有前端.UI方面的干货.一起来看下:) Swift 开源项 ...

  4. iOS越狱开发(一)

    做越狱开发也有一些时间了,有很多东西想总结一下,希望给他人一些借鉴,也是自己对过去开发经历的一些总结.个人不推荐使用盗版,这里主要以技术介绍为主. 这个系列里面主要介绍怎样进行越狱开发,涉及到以下几个 ...

  5. ng-表单验证

    表单验证<AngularJs>   常用的表单验证指令 1. 必填项验证 某个表单输入是否已填写,只要在输入字段元素上添加HTML5标记required即可: <input type ...

  6. Uvaoj10054 - The Necklace

    /* 题意:打印欧拉回路! 思路:开始时不明白,dfs为什么是后序遍历? 因为欧拉回路本身是一条回路,那么我们在dfs时,可能存在提前找到回路,这条回路可能不是欧拉回路, 因为没有遍历完成所有的边!如 ...

  7. ORA-32004

    今天在启动数据库的过程中,收到以下错误: SQL> startup ORA: obsolete or deprecated parameter(s) specified for RDBMS in ...

  8. tomcat架构之-----基本概念

    一直都没有搞明白tomcat中server.service.Engine.Host.Context概念的意义,最近认真看了<Tomcat 6 Developer Guide>,有了进一步的 ...

  9. 可视化工具solo show-----Prefuse自带例子GraphView讲解

    2014.10.15日以来的一个月,挤破了头.跑断了腿.伤透了心.吃够了全国最大餐饮连锁店——沙县小吃.其中酸甜苦辣,绝不是三言两语能够说得清道的明的.校招的兄弟姐妹们,你们懂得…… 体会最深的一句话 ...

  10. windows环境下跑hadoop自带的wordcount遇到的问题

    hadoop环境自己之前也接触过,搭建的是一个伪分布的环境,主从节点都在我自己的机子上,即127.0.0.1,当初记得步骤很多很麻烦的样子(可能自己用ubuntu还不够熟练),包括myeclipse. ...