feat: 切换后端至PaddleOCR-NCNN,切换工程为CMake

1.项目后端整体迁移至PaddleOCR-NCNN算法,已通过基本的兼容性测试
2.工程改为使用CMake组织,后续为了更好地兼容第三方库,不再提供QMake工程
3.重整权利声明文件,重整代码工程,确保最小化侵权风险

Log: 切换后端至PaddleOCR-NCNN,切换工程为CMake
Change-Id: I4d5d2c5d37505a4a24b389b1a4c5d12f17bfa38c
This commit is contained in:
wangzhengyang
2022-05-10 09:54:44 +08:00
parent ecdd171c6f
commit 718c41634f
10018 changed files with 3593797 additions and 186748 deletions

View File

@ -0,0 +1,452 @@
//*********************************************************
//
// Copyright (c) Microsoft. All rights reserved.
// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
//
//*********************************************************
#include "pch.h"
#include "LayoutAwarePage.h"
#include "SuspensionManager.h"
using namespace SDKSample::Common;
using namespace Platform;
using namespace Platform::Collections;
using namespace Windows::Foundation;
using namespace Windows::Foundation::Collections;
using namespace Windows::System;
using namespace Windows::UI::Core;
using namespace Windows::UI::ViewManagement;
using namespace Windows::UI::Xaml;
using namespace Windows::UI::Xaml::Controls;
using namespace Windows::UI::Xaml::Interop;
using namespace Windows::UI::Xaml::Navigation;
/// <summary>
/// Initializes a new instance of the <see cref="LayoutAwarePage"/> class.
/// </summary>
LayoutAwarePage::LayoutAwarePage()
{
if (Windows::ApplicationModel::DesignMode::DesignModeEnabled)
{
return;
}
// Create an empty default view model
DefaultViewModel = ref new Map<String^, Object^>(std::less<String^>());
// When this page is part of the visual tree make two changes:
// 1) Map application view state to visual state for the page
// 2) Handle keyboard and mouse navigation requests
Loaded += ref new RoutedEventHandler(this, &LayoutAwarePage::OnLoaded);
// Undo the same changes when the page is no longer visible
Unloaded += ref new RoutedEventHandler(this, &LayoutAwarePage::OnUnloaded);
}
static DependencyProperty^ _defaultViewModelProperty =
DependencyProperty::Register("DefaultViewModel",
TypeName(IObservableMap<String^, Object^>::typeid), TypeName(LayoutAwarePage::typeid), nullptr);
/// <summary>
/// Identifies the <see cref="DefaultViewModel"/> dependency property.
/// </summary>
DependencyProperty^ LayoutAwarePage::DefaultViewModelProperty::get()
{
return _defaultViewModelProperty;
}
/// <summary>
/// Gets an implementation of <see cref="IObservableMap&lt;String, Object&gt;"/> designed to be
/// used as a trivial view model.
/// </summary>
IObservableMap<String^, Object^>^ LayoutAwarePage::DefaultViewModel::get()
{
return safe_cast<IObservableMap<String^, Object^>^>(GetValue(DefaultViewModelProperty));
}
/// <summary>
/// Sets an implementation of <see cref="IObservableMap&lt;String, Object&gt;"/> designed to be
/// used as a trivial view model.
/// </summary>
void LayoutAwarePage::DefaultViewModel::set(IObservableMap<String^, Object^>^ value)
{
SetValue(DefaultViewModelProperty, value);
}
/// <summary>
/// Invoked when the page is part of the visual tree
/// </summary>
/// <param name="sender">Instance that triggered the event.</param>
/// <param name="e">Event data describing the conditions that led to the event.</param>
void LayoutAwarePage::OnLoaded(Object^ sender, Windows::UI::Xaml::RoutedEventArgs^ e)
{
this->StartLayoutUpdates(sender, e);
// Keyboard and mouse navigation only apply when occupying the entire window
if (this->ActualHeight == Window::Current->Bounds.Height &&
this->ActualWidth == Window::Current->Bounds.Width)
{
// Listen to the window directly so focus isn't required
_acceleratorKeyEventToken = Window::Current->CoreWindow->Dispatcher->AcceleratorKeyActivated +=
ref new TypedEventHandler<CoreDispatcher^, AcceleratorKeyEventArgs^>(this,
&LayoutAwarePage::CoreDispatcher_AcceleratorKeyActivated);
_pointerPressedEventToken = Window::Current->CoreWindow->PointerPressed +=
ref new TypedEventHandler<CoreWindow^, PointerEventArgs^>(this,
&LayoutAwarePage::CoreWindow_PointerPressed);
_navigationShortcutsRegistered = true;
}
}
/// <summary>
/// Invoked when the page is removed from visual tree
/// </summary>
/// <param name="sender">Instance that triggered the event.</param>
/// <param name="e">Event data describing the conditions that led to the event.</param>
void LayoutAwarePage::OnUnloaded(Object^ sender, Windows::UI::Xaml::RoutedEventArgs^ e)
{
if (_navigationShortcutsRegistered)
{
Window::Current->CoreWindow->Dispatcher->AcceleratorKeyActivated -= _acceleratorKeyEventToken;
Window::Current->CoreWindow->PointerPressed -= _pointerPressedEventToken;
_navigationShortcutsRegistered = false;
}
StopLayoutUpdates(sender, e);
}
#pragma region Navigation support
/// <summary>
/// Invoked as an event handler to navigate backward in the page's associated <see cref="Frame"/>
/// until it reaches the top of the navigation stack.
/// </summary>
/// <param name="sender">Instance that triggered the event.</param>
/// <param name="e">Event data describing the conditions that led to the event.</param>
void LayoutAwarePage::GoHome(Object^ sender, RoutedEventArgs^ e)
{
(void) sender; // Unused parameter
(void) e; // Unused parameter
// Use the navigation frame to return to the topmost page
if (Frame != nullptr)
{
while (Frame->CanGoBack)
{
Frame->GoBack();
}
}
}
/// <summary>
/// Invoked as an event handler to navigate backward in the navigation stack
/// associated with this page's <see cref="Frame"/>.
/// </summary>
/// <param name="sender">Instance that triggered the event.</param>
/// <param name="e">Event data describing the conditions that led to the event.</param>
void LayoutAwarePage::GoBack(Object^ sender, RoutedEventArgs^ e)
{
(void) sender; // Unused parameter
(void) e; // Unused parameter
// Use the navigation frame to return to the previous page
if (Frame != nullptr && Frame->CanGoBack)
{
Frame->GoBack();
}
}
/// <summary>
/// Invoked as an event handler to navigate forward in the navigation stack
/// associated with this page's <see cref="Frame"/>.
/// </summary>
/// <param name="sender">Instance that triggered the event.</param>
/// <param name="e">Event data describing the conditions that led to the event.</param>
void LayoutAwarePage::GoForward(Object^ sender, RoutedEventArgs^ e)
{
(void) sender; // Unused parameter
(void) e; // Unused parameter
// Use the navigation frame to advance to the next page
if (Frame != nullptr && Frame->CanGoForward)
{
Frame->GoForward();
}
}
/// <summary>
/// Invoked on every keystroke, including system keys such as Alt key combinations, when
/// this page is active and occupies the entire window. Used to detect keyboard navigation
/// between pages even when the page itself doesn't have focus.
/// </summary>
/// <param name="sender">Instance that triggered the event.</param>
/// <param name="args">Event data describing the conditions that led to the event.</param>
void LayoutAwarePage::CoreDispatcher_AcceleratorKeyActivated(CoreDispatcher^ sender, AcceleratorKeyEventArgs^ args)
{
auto virtualKey = args->VirtualKey;
// Only investigate further when Left, Right, or the dedicated Previous or Next keys
// are pressed
if ((args->EventType == CoreAcceleratorKeyEventType::SystemKeyDown ||
args->EventType == CoreAcceleratorKeyEventType::KeyDown) &&
(virtualKey == VirtualKey::Left || virtualKey == VirtualKey::Right ||
(int)virtualKey == 166 || (int)virtualKey == 167))
{
auto coreWindow = Window::Current->CoreWindow;
auto downState = Windows::UI::Core::CoreVirtualKeyStates::Down;
bool menuKey = (coreWindow->GetKeyState(VirtualKey::Menu) & downState) == downState;
bool controlKey = (coreWindow->GetKeyState(VirtualKey::Control) & downState) == downState;
bool shiftKey = (coreWindow->GetKeyState(VirtualKey::Shift) & downState) == downState;
bool noModifiers = !menuKey && !controlKey && !shiftKey;
bool onlyAlt = menuKey && !controlKey && !shiftKey;
if (((int)virtualKey == 166 && noModifiers) ||
(virtualKey == VirtualKey::Left && onlyAlt))
{
// When the previous key or Alt+Left are pressed navigate back
args->Handled = true;
GoBack(this, ref new RoutedEventArgs());
}
else if (((int)virtualKey == 167 && noModifiers) ||
(virtualKey == VirtualKey::Right && onlyAlt))
{
// When the next key or Alt+Right are pressed navigate forward
args->Handled = true;
GoForward(this, ref new RoutedEventArgs());
}
}
}
/// <summary>
/// Invoked on every mouse click, touch screen tap, or equivalent interaction when this
/// page is active and occupies the entire window. Used to detect browser-style next and
/// previous mouse button clicks to navigate between pages.
/// </summary>
/// <param name="sender">Instance that triggered the event.</param>
/// <param name="args">Event data describing the conditions that led to the event.</param>
void LayoutAwarePage::CoreWindow_PointerPressed(CoreWindow^ sender, PointerEventArgs^ args)
{
auto properties = args->CurrentPoint->Properties;
// Ignore button chords with the left, right, and middle buttons
if (properties->IsLeftButtonPressed || properties->IsRightButtonPressed ||
properties->IsMiddleButtonPressed) return;
// If back or forward are pressed (but not both) navigate appropriately
bool backPressed = properties->IsXButton1Pressed;
bool forwardPressed = properties->IsXButton2Pressed;
if (backPressed ^ forwardPressed)
{
args->Handled = true;
if (backPressed) GoBack(this, ref new RoutedEventArgs());
if (forwardPressed) GoForward(this, ref new RoutedEventArgs());
}
}
#pragma endregion
#pragma region Visual state switching
/// <summary>
/// Invoked as an event handler, typically on the <see cref="Loaded"/> event of a
/// <see cref="Control"/> within the page, to indicate that the sender should start receiving
/// visual state management changes that correspond to application view state changes.
/// </summary>
/// <param name="sender">Instance of <see cref="Control"/> that supports visual state management
/// corresponding to view states.</param>
/// <param name="e">Event data that describes how the request was made.</param>
/// <remarks>The current view state will immediately be used to set the corresponding visual state
/// when layout updates are requested. A corresponding <see cref="Unloaded"/> event handler
/// connected to <see cref="StopLayoutUpdates"/> is strongly encouraged. Instances of
/// <see cref="LayoutAwarePage"/> automatically invoke these handlers in their Loaded and Unloaded
/// events.</remarks>
/// <seealso cref="DetermineVisualState"/>
/// <seealso cref="InvalidateVisualState"/>
void LayoutAwarePage::StartLayoutUpdates(Object^ sender, RoutedEventArgs^ e)
{
(void) e; // Unused parameter
auto control = safe_cast<Control^>(sender);
if (_layoutAwareControls == nullptr)
{
// Start listening to view state changes when there are controls interested in updates
_layoutAwareControls = ref new Vector<Control^>();
_windowSizeEventToken = Window::Current->SizeChanged += ref new WindowSizeChangedEventHandler(this, &LayoutAwarePage::WindowSizeChanged);
// Page receives notifications for children. Protect the page until we stopped layout updates for all controls.
_this = this;
}
_layoutAwareControls->Append(control);
// Set the initial visual state of the control
VisualStateManager::GoToState(control, DetermineVisualState(ApplicationView::Value), false);
}
void LayoutAwarePage::WindowSizeChanged(Object^ sender, Windows::UI::Core::WindowSizeChangedEventArgs^ e)
{
(void) sender; // Unused parameter
(void) e; // Unused parameter
InvalidateVisualState();
}
/// <summary>
/// Invoked as an event handler, typically on the <see cref="Unloaded"/> event of a
/// <see cref="Control"/>, to indicate that the sender should start receiving visual state
/// management changes that correspond to application view state changes.
/// </summary>
/// <param name="sender">Instance of <see cref="Control"/> that supports visual state management
/// corresponding to view states.</param>
/// <param name="e">Event data that describes how the request was made.</param>
/// <remarks>The current view state will immediately be used to set the corresponding visual state
/// when layout updates are requested.</remarks>
/// <seealso cref="StartLayoutUpdates"/>
void LayoutAwarePage::StopLayoutUpdates(Object^ sender, RoutedEventArgs^ e)
{
(void) e; // Unused parameter
auto control = safe_cast<Control^>(sender);
unsigned int index;
if (_layoutAwareControls != nullptr && _layoutAwareControls->IndexOf(control, &index))
{
_layoutAwareControls->RemoveAt(index);
if (_layoutAwareControls->Size == 0)
{
// Stop listening to view state changes when no controls are interested in updates
Window::Current->SizeChanged -= _windowSizeEventToken;
_layoutAwareControls = nullptr;
// Last control has received the Unload notification.
_this = nullptr;
}
}
}
/// <summary>
/// Translates <see cref="ApplicationViewState"/> values into strings for visual state management
/// within the page. The default implementation uses the names of enum values. Subclasses may
/// override this method to control the mapping scheme used.
/// </summary>
/// <param name="viewState">View state for which a visual state is desired.</param>
/// <returns>Visual state name used to drive the <see cref="VisualStateManager"/></returns>
/// <seealso cref="InvalidateVisualState"/>
String^ LayoutAwarePage::DetermineVisualState(ApplicationViewState viewState)
{
switch (viewState)
{
case ApplicationViewState::Filled:
return "Filled";
case ApplicationViewState::Snapped:
return "Snapped";
case ApplicationViewState::FullScreenPortrait:
return "FullScreenPortrait";
case ApplicationViewState::FullScreenLandscape:
default:
return "FullScreenLandscape";
}
}
/// <summary>
/// Updates all controls that are listening for visual state changes with the correct visual
/// state.
/// </summary>
/// <remarks>
/// Typically used in conjunction with overriding <see cref="DetermineVisualState"/> to
/// signal that a different value may be returned even though the view state has not changed.
/// </remarks>
void LayoutAwarePage::InvalidateVisualState()
{
if (_layoutAwareControls != nullptr)
{
String^ visualState = DetermineVisualState(ApplicationView::Value);
auto controlIterator = _layoutAwareControls->First();
while (controlIterator->HasCurrent)
{
auto control = controlIterator->Current;
VisualStateManager::GoToState(control, visualState, false);
controlIterator->MoveNext();
}
}
}
#pragma endregion
#pragma region Process lifetime management
/// <summary>
/// Invoked when this page is about to be displayed in a Frame.
/// </summary>
/// <param name="e">Event data that describes how this page was reached. The Parameter
/// property provides the group to be displayed.</param>
void LayoutAwarePage::OnNavigatedTo(NavigationEventArgs^ e)
{
// Returning to a cached page through navigation shouldn't trigger state loading
if (_pageKey != nullptr) return;
auto frameState = SuspensionManager::SessionStateForFrame(Frame);
_pageKey = "Page-" + Frame->BackStackDepth;
if (e->NavigationMode == NavigationMode::New)
{
// Clear existing state for forward navigation when adding a new page to the
// navigation stack
auto nextPageKey = _pageKey;
int nextPageIndex = Frame->BackStackDepth;
while (frameState->HasKey(nextPageKey))
{
frameState->Remove(nextPageKey);
nextPageIndex++;
nextPageKey = "Page-" + nextPageIndex;
}
// Pass the navigation parameter to the new page
LoadState(e->Parameter, nullptr);
}
else
{
// Pass the navigation parameter and preserved page state to the page, using
// the same strategy for loading suspended state and recreating pages discarded
// from cache
LoadState(e->Parameter, safe_cast<IMap<String^, Object^>^>(frameState->Lookup(_pageKey)));
}
}
/// <summary>
/// Invoked when this page will no longer be displayed in a Frame.
/// </summary>
/// <param name="e">Event data that describes how this page was reached. The Parameter
/// property provides the group to be displayed.</param>
void LayoutAwarePage::OnNavigatedFrom(NavigationEventArgs^ e)
{
auto frameState = SuspensionManager::SessionStateForFrame(Frame);
auto pageState = ref new Map<String^, Object^>();
SaveState(pageState);
frameState->Insert(_pageKey, pageState);
}
/// <summary>
/// Populates the page with content passed during navigation. Any saved state is also
/// provided when recreating a page from a prior session.
/// </summary>
/// <param name="navigationParameter">The parameter value passed to
/// <see cref="Frame.Navigate(Type, Object)"/> when this page was initially requested.
/// </param>
/// <param name="pageState">A map of state preserved by this page during an earlier
/// session. This will be null the first time a page is visited.</param>
void LayoutAwarePage::LoadState(Object^ navigationParameter, IMap<String^, Object^>^ pageState)
{
}
/// <summary>
/// Preserves state associated with this page in case the application is suspended or the
/// page is discarded from the navigation cache. Values must conform to the serialization
/// requirements of <see cref="SuspensionManager.SessionState"/>.
/// </summary>
/// <param name="pageState">An empty map to be populated with serializable state.</param>
void LayoutAwarePage::SaveState(IMap<String^, Object^>^ pageState)
{
}
#pragma endregion

View File

@ -0,0 +1,88 @@
//*********************************************************
//
// Copyright (c) Microsoft. All rights reserved.
// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
//
//*********************************************************
#pragma once
#include <collection.h>
namespace SDKSample
{
namespace Common
{
/// <summary>
/// Typical implementation of Page that provides several important conveniences:
/// <list type="bullet">
/// <item>
/// <description>Application view state to visual state mapping</description>
/// </item>
/// <item>
/// <description>GoBack, GoForward, and GoHome event handlers</description>
/// </item>
/// <item>
/// <description>Mouse and keyboard shortcuts for navigation</description>
/// </item>
/// <item>
/// <description>State management for navigation and process lifetime management</description>
/// </item>
/// <item>
/// <description>A default view model</description>
/// </item>
/// </list>
/// </summary>
[Windows::Foundation::Metadata::WebHostHidden]
public ref class LayoutAwarePage : Windows::UI::Xaml::Controls::Page
{
internal:
LayoutAwarePage();
public:
void StartLayoutUpdates(Object^ sender, Windows::UI::Xaml::RoutedEventArgs^ e);
void StopLayoutUpdates(Object^ sender, Windows::UI::Xaml::RoutedEventArgs^ e);
void InvalidateVisualState();
static property Windows::UI::Xaml::DependencyProperty^ DefaultViewModelProperty
{
Windows::UI::Xaml::DependencyProperty^ get();
};
property Windows::Foundation::Collections::IObservableMap<Platform::String^, Platform::Object^>^ DefaultViewModel
{
Windows::Foundation::Collections::IObservableMap<Platform::String^, Platform::Object^>^ get();
void set(Windows::Foundation::Collections::IObservableMap<Platform::String^, Platform::Object^>^ value);
}
protected:
virtual void GoHome(Platform::Object^ sender, Windows::UI::Xaml::RoutedEventArgs^ e);
virtual void GoBack(Platform::Object^ sender, Windows::UI::Xaml::RoutedEventArgs^ e);
virtual void GoForward(Platform::Object^ sender, Windows::UI::Xaml::RoutedEventArgs^ e);
virtual Platform::String^ DetermineVisualState(Windows::UI::ViewManagement::ApplicationViewState viewState);
virtual void OnNavigatedTo(Windows::UI::Xaml::Navigation::NavigationEventArgs^ e) override;
virtual void OnNavigatedFrom(Windows::UI::Xaml::Navigation::NavigationEventArgs^ e) override;
virtual void LoadState(Platform::Object^ navigationParameter,
Windows::Foundation::Collections::IMap<Platform::String^, Platform::Object^>^ pageState);
virtual void SaveState(Windows::Foundation::Collections::IMap<Platform::String^, Platform::Object^>^ pageState);
private:
Platform::String^ _pageKey;
bool _navigationShortcutsRegistered;
Platform::Collections::Map<Platform::String^, Platform::Object^>^ _defaultViewModel;
Windows::Foundation::EventRegistrationToken _windowSizeEventToken,
_acceleratorKeyEventToken, _pointerPressedEventToken;
Platform::Collections::Vector<Windows::UI::Xaml::Controls::Control^>^ _layoutAwareControls;
void WindowSizeChanged(Platform::Object^ sender, Windows::UI::Core::WindowSizeChangedEventArgs^ e);
void OnLoaded(Object^ sender, Windows::UI::Xaml::RoutedEventArgs^ e);
void OnUnloaded(Object^ sender, Windows::UI::Xaml::RoutedEventArgs^ e);
void CoreDispatcher_AcceleratorKeyActivated(Windows::UI::Core::CoreDispatcher^ sender,
Windows::UI::Core::AcceleratorKeyEventArgs^ args);
void CoreWindow_PointerPressed(Windows::UI::Core::CoreWindow^ sender,
Windows::UI::Core::PointerEventArgs^ args);
LayoutAwarePage^ _this; // Strong reference to self, cleaned up in OnUnload
};
}
}

View File

@ -0,0 +1,978 @@
<!--
//*********************************************************
//
// Copyright (c) Microsoft. All rights reserved.
// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
//
//*********************************************************
-->
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<!-- Non-brush values that vary across themes -->
<ResourceDictionary.ThemeDictionaries>
<ResourceDictionary x:Key="Default">
<x:String x:Key="BackButtonGlyph">&#xE071;</x:String>
<x:String x:Key="BackButtonSnappedGlyph">&#xE0BA;</x:String>
</ResourceDictionary>
<ResourceDictionary x:Key="HighContrast">
<x:String x:Key="BackButtonGlyph">&#xE0A6;</x:String>
<x:String x:Key="BackButtonSnappedGlyph">&#xE0C4;</x:String>
</ResourceDictionary>
</ResourceDictionary.ThemeDictionaries>
<!-- RichTextBlock styles -->
<Style x:Key="BasicRichTextStyle" TargetType="RichTextBlock">
<Setter Property="Foreground" Value="{StaticResource ApplicationForegroundThemeBrush}"/>
<Setter Property="FontSize" Value="{StaticResource ControlContentThemeFontSize}"/>
<Setter Property="FontFamily" Value="{StaticResource ContentControlThemeFontFamily}"/>
<Setter Property="TextTrimming" Value="WordEllipsis"/>
<Setter Property="TextWrapping" Value="Wrap"/>
<Setter Property="Typography.StylisticSet20" Value="True"/>
<Setter Property="Typography.DiscretionaryLigatures" Value="True"/>
</Style>
<Style x:Key="BaselineRichTextStyle" TargetType="RichTextBlock" BasedOn="{StaticResource BasicRichTextStyle}">
<Setter Property="LineHeight" Value="20"/>
<Setter Property="LineStackingStrategy" Value="BlockLineHeight"/>
<!-- Properly align text along its baseline -->
<Setter Property="RenderTransform">
<Setter.Value>
<TranslateTransform X="-1" Y="4"/>
</Setter.Value>
</Setter>
</Style>
<Style x:Key="ItemRichTextStyle" TargetType="RichTextBlock" BasedOn="{StaticResource BaselineRichTextStyle}"/>
<Style x:Key="BodyRichTextStyle" TargetType="RichTextBlock" BasedOn="{StaticResource BaselineRichTextStyle}">
<Setter Property="FontWeight" Value="SemiLight"/>
</Style>
<!-- TextBlock styles -->
<Style x:Key="BasicTextStyle" TargetType="TextBlock">
<Setter Property="Foreground" Value="{StaticResource ApplicationForegroundThemeBrush}"/>
<Setter Property="FontSize" Value="{StaticResource ControlContentThemeFontSize}"/>
<Setter Property="FontFamily" Value="{StaticResource ContentControlThemeFontFamily}"/>
<Setter Property="TextTrimming" Value="WordEllipsis"/>
<Setter Property="TextWrapping" Value="Wrap"/>
<Setter Property="Typography.StylisticSet20" Value="True"/>
<Setter Property="Typography.DiscretionaryLigatures" Value="True"/>
</Style>
<Style x:Key="BaselineTextStyle" TargetType="TextBlock" BasedOn="{StaticResource BasicTextStyle}">
<Setter Property="LineHeight" Value="20"/>
<Setter Property="LineStackingStrategy" Value="BlockLineHeight"/>
<!-- Properly align text along its baseline -->
<Setter Property="RenderTransform">
<Setter.Value>
<TranslateTransform X="-1" Y="4"/>
</Setter.Value>
</Setter>
</Style>
<Style x:Key="HeaderTextStyle" TargetType="TextBlock" BasedOn="{StaticResource BaselineTextStyle}">
<Setter Property="FontSize" Value="56"/>
<Setter Property="FontWeight" Value="Light"/>
<Setter Property="LineHeight" Value="40"/>
<Setter Property="RenderTransform">
<Setter.Value>
<TranslateTransform X="-2" Y="8"/>
</Setter.Value>
</Setter>
</Style>
<Style x:Key="SubheaderTextStyle" TargetType="TextBlock" BasedOn="{StaticResource BaselineTextStyle}">
<Setter Property="FontSize" Value="26.667"/>
<Setter Property="FontWeight" Value="Light"/>
<Setter Property="LineHeight" Value="30"/>
<Setter Property="RenderTransform">
<Setter.Value>
<TranslateTransform X="-1" Y="6"/>
</Setter.Value>
</Setter>
</Style>
<Style x:Key="TitleTextStyle" TargetType="TextBlock" BasedOn="{StaticResource BaselineTextStyle}">
<Setter Property="FontWeight" Value="SemiBold"/>
</Style>
<Style x:Key="ItemTextStyle" TargetType="TextBlock" BasedOn="{StaticResource BaselineTextStyle}"/>
<Style x:Key="BodyTextStyle" TargetType="TextBlock" BasedOn="{StaticResource BaselineTextStyle}">
<Setter Property="FontWeight" Value="SemiLight"/>
</Style>
<Style x:Key="CaptionTextStyle" TargetType="TextBlock" BasedOn="{StaticResource BaselineTextStyle}">
<Setter Property="FontSize" Value="12"/>
<Setter Property="Foreground" Value="{StaticResource ApplicationSecondaryForegroundThemeBrush}"/>
</Style>
<!-- Button styles -->
<!--
TextButtonStyle is used to style a Button using subheader-styled text with no other adornment. This
style is used in the GroupedItemsPage as a group header and in the FileOpenPickerPage for triggering
commands.
-->
<Style x:Key="TextButtonStyle" TargetType="Button">
<Setter Property="MinWidth" Value="0"/>
<Setter Property="MinHeight" Value="0"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Grid Background="Transparent">
<TextBlock
x:Name="Text"
Text="{TemplateBinding Content}"
Margin="3,-7,3,10"
TextWrapping="NoWrap"
Style="{StaticResource SubheaderTextStyle}"/>
<Rectangle
x:Name="FocusVisualWhite"
IsHitTestVisible="False"
Stroke="{StaticResource FocusVisualWhiteStrokeThemeBrush}"
StrokeEndLineCap="Square"
StrokeDashArray="1,1"
Opacity="0"
StrokeDashOffset="1.5"/>
<Rectangle
x:Name="FocusVisualBlack"
IsHitTestVisible="False"
Stroke="{StaticResource FocusVisualBlackStrokeThemeBrush}"
StrokeEndLineCap="Square"
StrokeDashArray="1,1"
Opacity="0"
StrokeDashOffset="0.5"/>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal"/>
<VisualState x:Name="PointerOver">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="Text" Storyboard.TargetProperty="Foreground">
<DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource ApplicationPointerOverForegroundThemeBrush}"/>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="Pressed">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="Text" Storyboard.TargetProperty="Foreground">
<DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource ApplicationPressedForegroundThemeBrush}"/>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="Disabled">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="Text" Storyboard.TargetProperty="Foreground">
<DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource ButtonDisabledForegroundThemeBrush}"/>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
</VisualStateGroup>
<VisualStateGroup x:Name="FocusStates">
<VisualState x:Name="Focused">
<Storyboard>
<DoubleAnimation Duration="0" To="1" Storyboard.TargetName="FocusVisualWhite" Storyboard.TargetProperty="Opacity"/>
<DoubleAnimation Duration="0" To="1" Storyboard.TargetName="FocusVisualBlack" Storyboard.TargetProperty="Opacity"/>
</Storyboard>
</VisualState>
<VisualState x:Name="Unfocused"/>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<!--
TextRadioButtonStyle is used to style a RadioButton using subheader-styled text with no other adornment.
This style is used in the SearchResultsPage to allow selection among filters.
-->
<Style x:Key="TextRadioButtonStyle" TargetType="RadioButton">
<Setter Property="MinWidth" Value="0"/>
<Setter Property="MinHeight" Value="0"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="RadioButton">
<Grid Background="Transparent">
<TextBlock
x:Name="Text"
Text="{TemplateBinding Content}"
Margin="3,-7,3,10"
TextWrapping="NoWrap"
Style="{StaticResource SubheaderTextStyle}"/>
<Rectangle
x:Name="FocusVisualWhite"
IsHitTestVisible="False"
Stroke="{StaticResource FocusVisualWhiteStrokeThemeBrush}"
StrokeEndLineCap="Square"
StrokeDashArray="1,1"
Opacity="0"
StrokeDashOffset="1.5"/>
<Rectangle
x:Name="FocusVisualBlack"
IsHitTestVisible="False"
Stroke="{StaticResource FocusVisualBlackStrokeThemeBrush}"
StrokeEndLineCap="Square"
StrokeDashArray="1,1"
Opacity="0"
StrokeDashOffset="0.5"/>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal"/>
<VisualState x:Name="PointerOver">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="Text" Storyboard.TargetProperty="Foreground">
<DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource ApplicationPointerOverForegroundThemeBrush}"/>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="Pressed">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="Text" Storyboard.TargetProperty="Foreground">
<DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource ApplicationPressedForegroundThemeBrush}"/>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="Disabled">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="Text" Storyboard.TargetProperty="Foreground">
<DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource ButtonDisabledForegroundThemeBrush}"/>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
</VisualStateGroup>
<VisualStateGroup x:Name="FocusStates">
<VisualState x:Name="Focused">
<Storyboard>
<DoubleAnimation Duration="0" To="1" Storyboard.TargetName="FocusVisualWhite" Storyboard.TargetProperty="Opacity"/>
<DoubleAnimation Duration="0" To="1" Storyboard.TargetName="FocusVisualBlack" Storyboard.TargetProperty="Opacity"/>
</Storyboard>
</VisualState>
<VisualState x:Name="Unfocused"/>
</VisualStateGroup>
<VisualStateGroup x:Name="CheckStates">
<VisualState x:Name="Checked"/>
<VisualState x:Name="Unchecked">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="Text" Storyboard.TargetProperty="Foreground">
<DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource ApplicationSecondaryForegroundThemeBrush}"/>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="Indeterminate"/>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<!--
AppBarButtonStyle is used to style a Button for use in an App Bar. Content will be centered and should fit within
the 40-pixel radius glyph provided. 16-point Segoe UI Symbol is used for content text to simplify the use of glyphs
from that font. AutomationProperties.Name is used for the text below the glyph.
-->
<Style x:Key="AppBarButtonStyle" TargetType="Button">
<Setter Property="Foreground" Value="{StaticResource AppBarItemForegroundThemeBrush}"/>
<Setter Property="VerticalAlignment" Value="Stretch"/>
<Setter Property="FontFamily" Value="Segoe UI Symbol"/>
<Setter Property="FontWeight" Value="Normal"/>
<Setter Property="FontSize" Value="20"/>
<Setter Property="AutomationProperties.ItemType" Value="App Bar Button"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Grid Width="100" Background="Transparent">
<StackPanel VerticalAlignment="Top" Margin="0,14,0,13">
<Grid Width="40" Height="40" Margin="0,0,0,5" HorizontalAlignment="Center">
<TextBlock x:Name="BackgroundGlyph" Text="&#xE0A8;" FontFamily="Segoe UI Symbol" FontSize="53.333" Margin="-4,-19,0,0" Foreground="{StaticResource AppBarItemBackgroundThemeBrush}"/>
<TextBlock x:Name="OutlineGlyph" Text="&#xE0A7;" FontFamily="Segoe UI Symbol" FontSize="53.333" Margin="-4,-19,0,0"/>
<ContentPresenter x:Name="Content" HorizontalAlignment="Center" Margin="-1,-1,0,0" VerticalAlignment="Center"/>
</Grid>
<TextBlock
x:Name="TextLabel"
Text="{TemplateBinding AutomationProperties.Name}"
Margin="0,0,2,0"
FontSize="12"
TextAlignment="Center"
Width="88"
MaxHeight="32"
TextTrimming="WordEllipsis"
Style="{StaticResource BasicTextStyle}"/>
</StackPanel>
<Rectangle
x:Name="FocusVisualWhite"
IsHitTestVisible="False"
Stroke="{StaticResource FocusVisualWhiteStrokeThemeBrush}"
StrokeEndLineCap="Square"
StrokeDashArray="1,1"
Opacity="0"
StrokeDashOffset="1.5"/>
<Rectangle
x:Name="FocusVisualBlack"
IsHitTestVisible="False"
Stroke="{StaticResource FocusVisualBlackStrokeThemeBrush}"
StrokeEndLineCap="Square"
StrokeDashArray="1,1"
Opacity="0"
StrokeDashOffset="0.5"/>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal"/>
<VisualState x:Name="PointerOver">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="BackgroundGlyph" Storyboard.TargetProperty="Foreground">
<DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource AppBarItemPointerOverBackgroundThemeBrush}"/>
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="Content" Storyboard.TargetProperty="Foreground">
<DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource AppBarItemPointerOverForegroundThemeBrush}"/>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="Pressed">
<Storyboard>
<DoubleAnimation
Storyboard.TargetName="OutlineGlyph"
Storyboard.TargetProperty="Opacity"
To="0"
Duration="0"/>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="BackgroundGlyph" Storyboard.TargetProperty="Foreground">
<DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource AppBarItemForegroundThemeBrush}"/>
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="Content" Storyboard.TargetProperty="Foreground">
<DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource AppBarItemPressedForegroundThemeBrush}"/>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="Disabled">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="OutlineGlyph" Storyboard.TargetProperty="Foreground">
<DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource AppBarItemDisabledForegroundThemeBrush}"/>
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="Content" Storyboard.TargetProperty="Foreground">
<DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource AppBarItemDisabledForegroundThemeBrush}"/>
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="TextLabel" Storyboard.TargetProperty="Foreground">
<DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource AppBarItemDisabledForegroundThemeBrush}"/>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
</VisualStateGroup>
<VisualStateGroup x:Name="FocusStates">
<VisualState x:Name="Focused">
<Storyboard>
<DoubleAnimation
Storyboard.TargetName="FocusVisualWhite"
Storyboard.TargetProperty="Opacity"
To="1"
Duration="0"/>
<DoubleAnimation
Storyboard.TargetName="FocusVisualBlack"
Storyboard.TargetProperty="Opacity"
To="1"
Duration="0"/>
</Storyboard>
</VisualState>
<VisualState x:Name="Unfocused" />
<VisualState x:Name="PointerFocused" />
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<!-- Standard App Bar buttons -->
<Style x:Key="SkipBackAppBarButtonStyle" TargetType="Button" BasedOn="{StaticResource AppBarButtonStyle}">
<Setter Property="AutomationProperties.AutomationId" Value="SkipBackAppBarButton"/>
<Setter Property="AutomationProperties.Name" Value="Skip Back"/>
<Setter Property="Content" Value="&#xE100;"/>
</Style>
<Style x:Key="SkipAheadAppBarButtonStyle" TargetType="Button" BasedOn="{StaticResource AppBarButtonStyle}">
<Setter Property="AutomationProperties.AutomationId" Value="SkipAheadAppBarButton"/>
<Setter Property="AutomationProperties.Name" Value="Skip Ahead"/>
<Setter Property="Content" Value="&#xE101;"/>
</Style>
<Style x:Key="PlayAppBarButtonStyle" TargetType="Button" BasedOn="{StaticResource AppBarButtonStyle}">
<Setter Property="AutomationProperties.AutomationId" Value="PlayAppBarButton"/>
<Setter Property="AutomationProperties.Name" Value="Play"/>
<Setter Property="Content" Value="&#xE102;"/>
</Style>
<Style x:Key="PauseAppBarButtonStyle" TargetType="Button" BasedOn="{StaticResource AppBarButtonStyle}">
<Setter Property="AutomationProperties.AutomationId" Value="PauseAppBarButton"/>
<Setter Property="AutomationProperties.Name" Value="Pause"/>
<Setter Property="Content" Value="&#xE103;"/>
</Style>
<Style x:Key="EditAppBarButtonStyle" TargetType="Button" BasedOn="{StaticResource AppBarButtonStyle}">
<Setter Property="AutomationProperties.AutomationId" Value="EditAppBarButton"/>
<Setter Property="AutomationProperties.Name" Value="Edit"/>
<Setter Property="Content" Value="&#xE104;"/>
</Style>
<Style x:Key="SaveAppBarButtonStyle" TargetType="Button" BasedOn="{StaticResource AppBarButtonStyle}">
<Setter Property="AutomationProperties.AutomationId" Value="SaveAppBarButton"/>
<Setter Property="AutomationProperties.Name" Value="Save"/>
<Setter Property="Content" Value="&#xE105;"/>
</Style>
<Style x:Key="DeleteAppBarButtonStyle" TargetType="Button" BasedOn="{StaticResource AppBarButtonStyle}">
<Setter Property="AutomationProperties.AutomationId" Value="DeleteAppBarButton"/>
<Setter Property="AutomationProperties.Name" Value="Delete"/>
<Setter Property="Content" Value="&#xE106;"/>
</Style>
<Style x:Key="DiscardAppBarButtonStyle" TargetType="Button" BasedOn="{StaticResource AppBarButtonStyle}">
<Setter Property="AutomationProperties.AutomationId" Value="DiscardAppBarButton"/>
<Setter Property="AutomationProperties.Name" Value="Discard"/>
<Setter Property="Content" Value="&#xE107;"/>
</Style>
<Style x:Key="RemoveAppBarButtonStyle" TargetType="Button" BasedOn="{StaticResource AppBarButtonStyle}">
<Setter Property="AutomationProperties.AutomationId" Value="RemoveAppBarButton"/>
<Setter Property="AutomationProperties.Name" Value="Remove"/>
<Setter Property="Content" Value="&#xE108;"/>
</Style>
<Style x:Key="AddAppBarButtonStyle" TargetType="Button" BasedOn="{StaticResource AppBarButtonStyle}">
<Setter Property="AutomationProperties.AutomationId" Value="AddAppBarButton"/>
<Setter Property="AutomationProperties.Name" Value="Add"/>
<Setter Property="Content" Value="&#xE109;"/>
</Style>
<Style x:Key="NoAppBarButtonStyle" TargetType="Button" BasedOn="{StaticResource AppBarButtonStyle}">
<Setter Property="AutomationProperties.AutomationId" Value="NoAppBarButton"/>
<Setter Property="AutomationProperties.Name" Value="No"/>
<Setter Property="Content" Value="&#xE10A;"/>
</Style>
<Style x:Key="YesAppBarButtonStyle" TargetType="Button" BasedOn="{StaticResource AppBarButtonStyle}">
<Setter Property="AutomationProperties.AutomationId" Value="YesAppBarButton"/>
<Setter Property="AutomationProperties.Name" Value="Yes"/>
<Setter Property="Content" Value="&#xE10B;"/>
</Style>
<Style x:Key="MoreAppBarButtonStyle" TargetType="Button" BasedOn="{StaticResource AppBarButtonStyle}">
<Setter Property="AutomationProperties.AutomationId" Value="MoreAppBarButton"/>
<Setter Property="AutomationProperties.Name" Value="More"/>
<Setter Property="Content" Value="&#xE10C;"/>
</Style>
<Style x:Key="RedoAppBarButtonStyle" TargetType="Button" BasedOn="{StaticResource AppBarButtonStyle}">
<Setter Property="AutomationProperties.AutomationId" Value="RedoAppBarButton"/>
<Setter Property="AutomationProperties.Name" Value="Redo"/>
<Setter Property="Content" Value="&#xE10D;"/>
</Style>
<Style x:Key="UndoAppBarButtonStyle" TargetType="Button" BasedOn="{StaticResource AppBarButtonStyle}">
<Setter Property="AutomationProperties.AutomationId" Value="UndoAppBarButton"/>
<Setter Property="AutomationProperties.Name" Value="Undo"/>
<Setter Property="Content" Value="&#xE10E;"/>
</Style>
<Style x:Key="HomeAppBarButtonStyle" TargetType="Button" BasedOn="{StaticResource AppBarButtonStyle}">
<Setter Property="AutomationProperties.AutomationId" Value="HomeAppBarButton"/>
<Setter Property="AutomationProperties.Name" Value="Home"/>
<Setter Property="Content" Value="&#xE10F;"/>
</Style>
<Style x:Key="OutAppBarButtonStyle" TargetType="Button" BasedOn="{StaticResource AppBarButtonStyle}">
<Setter Property="AutomationProperties.AutomationId" Value="OutAppBarButton"/>
<Setter Property="AutomationProperties.Name" Value="Out"/>
<Setter Property="Content" Value="&#xE110;"/>
</Style>
<Style x:Key="NextAppBarButtonStyle" TargetType="Button" BasedOn="{StaticResource AppBarButtonStyle}">
<Setter Property="AutomationProperties.AutomationId" Value="NextAppBarButton"/>
<Setter Property="AutomationProperties.Name" Value="Next"/>
<Setter Property="Content" Value="&#xE111;"/>
</Style>
<Style x:Key="PreviousAppBarButtonStyle" TargetType="Button" BasedOn="{StaticResource AppBarButtonStyle}">
<Setter Property="AutomationProperties.AutomationId" Value="PreviousAppBarButton"/>
<Setter Property="AutomationProperties.Name" Value="Previous"/>
<Setter Property="Content" Value="&#xE112;"/>
</Style>
<Style x:Key="FavoriteAppBarButtonStyle" TargetType="Button" BasedOn="{StaticResource AppBarButtonStyle}">
<Setter Property="AutomationProperties.AutomationId" Value="FavoriteAppBarButton"/>
<Setter Property="AutomationProperties.Name" Value="Favorite"/>
<Setter Property="Content" Value="&#xE113;"/>
</Style>
<Style x:Key="PhotoAppBarButtonStyle" TargetType="Button" BasedOn="{StaticResource AppBarButtonStyle}">
<Setter Property="AutomationProperties.AutomationId" Value="PhotoAppBarButton"/>
<Setter Property="AutomationProperties.Name" Value="Photo"/>
<Setter Property="Content" Value="&#xE114;"/>
</Style>
<Style x:Key="SettingsAppBarButtonStyle" TargetType="Button" BasedOn="{StaticResource AppBarButtonStyle}">
<Setter Property="AutomationProperties.AutomationId" Value="SettingsAppBarButton"/>
<Setter Property="AutomationProperties.Name" Value="Settings"/>
<Setter Property="Content" Value="&#xE115;"/>
</Style>
<Style x:Key="VideoAppBarButtonStyle" TargetType="Button" BasedOn="{StaticResource AppBarButtonStyle}">
<Setter Property="AutomationProperties.AutomationId" Value="VideoAppBarButton"/>
<Setter Property="AutomationProperties.Name" Value="Video"/>
<Setter Property="Content" Value="&#xE116;"/>
</Style>
<Style x:Key="RefreshAppBarButtonStyle" TargetType="Button" BasedOn="{StaticResource AppBarButtonStyle}">
<Setter Property="AutomationProperties.AutomationId" Value="RefreshAppBarButton"/>
<Setter Property="AutomationProperties.Name" Value="Refresh"/>
<Setter Property="Content" Value="&#xE117;"/>
</Style>
<Style x:Key="DownloadAppBarButtonStyle" TargetType="Button" BasedOn="{StaticResource AppBarButtonStyle}">
<Setter Property="AutomationProperties.AutomationId" Value="DownloadAppBarButton"/>
<Setter Property="AutomationProperties.Name" Value="Download"/>
<Setter Property="Content" Value="&#xE118;"/>
</Style>
<Style x:Key="MailAppBarButtonStyle" TargetType="Button" BasedOn="{StaticResource AppBarButtonStyle}">
<Setter Property="AutomationProperties.AutomationId" Value="MailAppBarButton"/>
<Setter Property="AutomationProperties.Name" Value="Mail"/>
<Setter Property="Content" Value="&#xE119;"/>
</Style>
<Style x:Key="SearchAppBarButtonStyle" TargetType="Button" BasedOn="{StaticResource AppBarButtonStyle}">
<Setter Property="AutomationProperties.AutomationId" Value="SearchAppBarButton"/>
<Setter Property="AutomationProperties.Name" Value="Search"/>
<Setter Property="Content" Value="&#xE11A;"/>
</Style>
<Style x:Key="HelpAppBarButtonStyle" TargetType="Button" BasedOn="{StaticResource AppBarButtonStyle}">
<Setter Property="AutomationProperties.AutomationId" Value="HelpAppBarButton"/>
<Setter Property="AutomationProperties.Name" Value="Help"/>
<Setter Property="Content" Value="&#xE11B;"/>
</Style>
<Style x:Key="UploadAppBarButtonStyle" TargetType="Button" BasedOn="{StaticResource AppBarButtonStyle}">
<Setter Property="AutomationProperties.AutomationId" Value="UploadAppBarButton"/>
<Setter Property="AutomationProperties.Name" Value="Upload"/>
<Setter Property="Content" Value="&#xE11C;"/>
</Style>
<Style x:Key="PinAppBarButtonStyle" TargetType="Button" BasedOn="{StaticResource AppBarButtonStyle}">
<Setter Property="AutomationProperties.AutomationId" Value="PinAppBarButton"/>
<Setter Property="AutomationProperties.Name" Value="Pin"/>
<Setter Property="Content" Value="&#xE141;"/>
</Style>
<Style x:Key="UnpinAppBarButtonStyle" TargetType="Button" BasedOn="{StaticResource AppBarButtonStyle}">
<Setter Property="AutomationProperties.AutomationId" Value="UnpinAppBarButton"/>
<Setter Property="AutomationProperties.Name" Value="Unpin"/>
<Setter Property="Content" Value="&#xE196;"/>
</Style>
<!-- Title area styles -->
<Style x:Key="PageHeaderTextStyle" TargetType="TextBlock" BasedOn="{StaticResource HeaderTextStyle}">
<Setter Property="TextWrapping" Value="NoWrap"/>
<Setter Property="VerticalAlignment" Value="Bottom"/>
<Setter Property="Margin" Value="0,0,40,40"/>
</Style>
<Style x:Key="PageSubheaderTextStyle" TargetType="TextBlock" BasedOn="{StaticResource SubheaderTextStyle}">
<Setter Property="TextWrapping" Value="NoWrap"/>
<Setter Property="VerticalAlignment" Value="Bottom"/>
<Setter Property="Margin" Value="0,0,0,40"/>
</Style>
<Style x:Key="SnappedPageHeaderTextStyle" TargetType="TextBlock" BasedOn="{StaticResource PageSubheaderTextStyle}">
<Setter Property="Margin" Value="0,0,18,40"/>
</Style>
<!--
BackButtonStyle is used to style a Button for use in the title area of a page. Margins appropriate for
the conventional page layout are included as part of the style.
-->
<Style x:Key="BackButtonStyle" TargetType="Button">
<Setter Property="MinWidth" Value="0"/>
<Setter Property="Width" Value="48"/>
<Setter Property="Height" Value="48"/>
<Setter Property="Margin" Value="36,0,36,36"/>
<Setter Property="VerticalAlignment" Value="Bottom"/>
<Setter Property="FontFamily" Value="Segoe UI Symbol"/>
<Setter Property="FontWeight" Value="Normal"/>
<Setter Property="FontSize" Value="56"/>
<Setter Property="AutomationProperties.AutomationId" Value="BackButton"/>
<Setter Property="AutomationProperties.Name" Value="Back"/>
<Setter Property="AutomationProperties.ItemType" Value="Navigation Button"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Grid x:Name="RootGrid">
<Grid Margin="-1,-16,0,0">
<TextBlock x:Name="BackgroundGlyph" Text="&#xE0A8;" Foreground="{StaticResource BackButtonBackgroundThemeBrush}"/>
<TextBlock x:Name="NormalGlyph" Text="{StaticResource BackButtonGlyph}" Foreground="{StaticResource BackButtonForegroundThemeBrush}"/>
<TextBlock x:Name="ArrowGlyph" Text="&#xE0A6;" Foreground="{StaticResource BackButtonPressedForegroundThemeBrush}" Opacity="0"/>
</Grid>
<Rectangle
x:Name="FocusVisualWhite"
IsHitTestVisible="False"
Stroke="{StaticResource FocusVisualWhiteStrokeThemeBrush}"
StrokeEndLineCap="Square"
StrokeDashArray="1,1"
Opacity="0"
StrokeDashOffset="1.5"/>
<Rectangle
x:Name="FocusVisualBlack"
IsHitTestVisible="False"
Stroke="{StaticResource FocusVisualBlackStrokeThemeBrush}"
StrokeEndLineCap="Square"
StrokeDashArray="1,1"
Opacity="0"
StrokeDashOffset="0.5"/>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal" />
<VisualState x:Name="PointerOver">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="BackgroundGlyph" Storyboard.TargetProperty="Foreground">
<DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource BackButtonPointerOverBackgroundThemeBrush}"/>
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="NormalGlyph" Storyboard.TargetProperty="Foreground">
<DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource BackButtonPointerOverForegroundThemeBrush}"/>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="Pressed">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="BackgroundGlyph" Storyboard.TargetProperty="Foreground">
<DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource BackButtonForegroundThemeBrush}"/>
</ObjectAnimationUsingKeyFrames>
<DoubleAnimation
Storyboard.TargetName="ArrowGlyph"
Storyboard.TargetProperty="Opacity"
To="1"
Duration="0"/>
<DoubleAnimation
Storyboard.TargetName="NormalGlyph"
Storyboard.TargetProperty="Opacity"
To="0"
Duration="0"/>
</Storyboard>
</VisualState>
<VisualState x:Name="Disabled">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="RootGrid" Storyboard.TargetProperty="Visibility">
<DiscreteObjectKeyFrame KeyTime="0" Value="Collapsed"/>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
</VisualStateGroup>
<VisualStateGroup x:Name="FocusStates">
<VisualState x:Name="Focused">
<Storyboard>
<DoubleAnimation
Storyboard.TargetName="FocusVisualWhite"
Storyboard.TargetProperty="Opacity"
To="1"
Duration="0"/>
<DoubleAnimation
Storyboard.TargetName="FocusVisualBlack"
Storyboard.TargetProperty="Opacity"
To="1"
Duration="0"/>
</Storyboard>
</VisualState>
<VisualState x:Name="Unfocused" />
<VisualState x:Name="PointerFocused" />
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<!--
PortraitBackButtonStyle is used to style a Button for use in the title area of a portrait page. Margins appropriate
for the conventional page layout are included as part of the style.
-->
<Style x:Key="PortraitBackButtonStyle" TargetType="Button" BasedOn="{StaticResource BackButtonStyle}">
<Setter Property="Margin" Value="26,0,26,36"/>
</Style>
<!--
SnappedBackButtonStyle is used to style a Button for use in the title area of a snapped page. Margins appropriate
for the conventional page layout are included as part of the style.
The obvious duplication here is necessary as the glyphs used in snapped are not merely smaller versions of the same
glyph but are actually distinct.
-->
<Style x:Key="SnappedBackButtonStyle" TargetType="Button">
<Setter Property="MinWidth" Value="0"/>
<Setter Property="Margin" Value="20,0,0,0"/>
<Setter Property="VerticalAlignment" Value="Bottom"/>
<Setter Property="FontFamily" Value="Segoe UI Symbol"/>
<Setter Property="FontWeight" Value="Normal"/>
<Setter Property="FontSize" Value="26.66667"/>
<Setter Property="AutomationProperties.AutomationId" Value="BackButton"/>
<Setter Property="AutomationProperties.Name" Value="Back"/>
<Setter Property="AutomationProperties.ItemType" Value="Navigation Button"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Grid x:Name="RootGrid" Width="36" Height="36" Margin="-3,0,7,33">
<Grid Margin="-1,-1,0,0">
<TextBlock x:Name="BackgroundGlyph" Text="&#xE0D4;" Foreground="{StaticResource BackButtonBackgroundThemeBrush}"/>
<TextBlock x:Name="NormalGlyph" Text="{StaticResource BackButtonSnappedGlyph}" Foreground="{StaticResource BackButtonForegroundThemeBrush}"/>
<TextBlock x:Name="ArrowGlyph" Text="&#xE0C4;" Foreground="{StaticResource BackButtonPressedForegroundThemeBrush}" Opacity="0"/>
</Grid>
<Rectangle
x:Name="FocusVisualWhite"
IsHitTestVisible="False"
Stroke="{StaticResource FocusVisualWhiteStrokeThemeBrush}"
StrokeEndLineCap="Square"
StrokeDashArray="1,1"
Opacity="0"
StrokeDashOffset="1.5"/>
<Rectangle
x:Name="FocusVisualBlack"
IsHitTestVisible="False"
Stroke="{StaticResource FocusVisualBlackStrokeThemeBrush}"
StrokeEndLineCap="Square"
StrokeDashArray="1,1"
Opacity="0"
StrokeDashOffset="0.5"/>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal" />
<VisualState x:Name="PointerOver">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="BackgroundGlyph" Storyboard.TargetProperty="Foreground">
<DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource BackButtonPointerOverBackgroundThemeBrush}"/>
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="NormalGlyph" Storyboard.TargetProperty="Foreground">
<DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource BackButtonPointerOverForegroundThemeBrush}"/>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="Pressed">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="BackgroundGlyph" Storyboard.TargetProperty="Foreground">
<DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource BackButtonForegroundThemeBrush}"/>
</ObjectAnimationUsingKeyFrames>
<DoubleAnimation
Storyboard.TargetName="ArrowGlyph"
Storyboard.TargetProperty="Opacity"
To="1"
Duration="0"/>
<DoubleAnimation
Storyboard.TargetName="NormalGlyph"
Storyboard.TargetProperty="Opacity"
To="0"
Duration="0"/>
</Storyboard>
</VisualState>
<VisualState x:Name="Disabled">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="RootGrid" Storyboard.TargetProperty="Visibility">
<DiscreteObjectKeyFrame KeyTime="0" Value="Collapsed"/>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
</VisualStateGroup>
<VisualStateGroup x:Name="FocusStates">
<VisualState x:Name="Focused">
<Storyboard>
<DoubleAnimation
Storyboard.TargetName="FocusVisualWhite"
Storyboard.TargetProperty="Opacity"
To="1"
Duration="0"/>
<DoubleAnimation
Storyboard.TargetName="FocusVisualBlack"
Storyboard.TargetProperty="Opacity"
To="1"
Duration="0"/>
</Storyboard>
</VisualState>
<VisualState x:Name="Unfocused" />
<VisualState x:Name="PointerFocused" />
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<!-- Item templates -->
<!-- Grid-appropriate 250 pixel square item template as seen in the GroupedItemsPage and ItemsPage -->
<DataTemplate x:Key="Standard250x250ItemTemplate">
<Grid HorizontalAlignment="Left" Width="250" Height="250">
<Border Background="{StaticResource ListViewItemPlaceholderBackgroundThemeBrush}">
<Image Source="{Binding Image}" Stretch="UniformToFill"/>
</Border>
<StackPanel VerticalAlignment="Bottom" Background="{StaticResource ListViewItemOverlayBackgroundThemeBrush}">
<TextBlock Text="{Binding Title}" Foreground="{StaticResource ListViewItemOverlayForegroundThemeBrush}" Style="{StaticResource TitleTextStyle}" Height="60" Margin="15,0,15,0"/>
<TextBlock Text="{Binding Subtitle}" Foreground="{StaticResource ListViewItemOverlaySecondaryForegroundThemeBrush}" Style="{StaticResource CaptionTextStyle}" TextWrapping="NoWrap" Margin="15,0,15,10"/>
</StackPanel>
</Grid>
</DataTemplate>
<!-- Grid-appropriate 500 by 130 pixel item template as seen in the GroupDetailPage -->
<DataTemplate x:Key="Standard500x130ItemTemplate">
<Grid Height="110" Width="480" Margin="10">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Border Background="{StaticResource ListViewItemPlaceholderBackgroundThemeBrush}" Width="110" Height="110">
<Image Source="{Binding Image}" Stretch="UniformToFill"/>
</Border>
<StackPanel Grid.Column="1" VerticalAlignment="Top" Margin="10,0,0,0">
<TextBlock Text="{Binding Title}" Style="{StaticResource TitleTextStyle}" TextWrapping="NoWrap"/>
<TextBlock Text="{Binding Subtitle}" Style="{StaticResource CaptionTextStyle}" TextWrapping="NoWrap"/>
<TextBlock Text="{Binding Description}" Style="{StaticResource BodyTextStyle}" MaxHeight="60"/>
</StackPanel>
</Grid>
</DataTemplate>
<!-- List-appropriate 130 pixel high item template as seen in the SplitPage -->
<DataTemplate x:Key="Standard130ItemTemplate">
<Grid Height="110" Margin="6">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Border Background="{StaticResource ListViewItemPlaceholderBackgroundThemeBrush}" Width="110" Height="110">
<Image Source="{Binding Image}" Stretch="UniformToFill"/>
</Border>
<StackPanel Grid.Column="1" VerticalAlignment="Top" Margin="10,0,0,0">
<TextBlock Text="{Binding Title}" Style="{StaticResource TitleTextStyle}" TextWrapping="NoWrap"/>
<TextBlock Text="{Binding Subtitle}" Style="{StaticResource CaptionTextStyle}" TextWrapping="NoWrap"/>
<TextBlock Text="{Binding Description}" Style="{StaticResource BodyTextStyle}" MaxHeight="60"/>
</StackPanel>
</Grid>
</DataTemplate>
<!--
List-appropriate 80 pixel high item template as seen in the SplitPage when Filled, and
the following pages when snapped: GroupedItemsPage, GroupDetailPage, and ItemsPage
-->
<DataTemplate x:Key="Standard80ItemTemplate">
<Grid Margin="6">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Border Background="{StaticResource ListViewItemPlaceholderBackgroundThemeBrush}" Width="60" Height="60">
<Image Source="{Binding Image}" Stretch="UniformToFill"/>
</Border>
<StackPanel Grid.Column="1" Margin="10,0,0,0">
<TextBlock Text="{Binding Title}" Style="{StaticResource ItemTextStyle}" MaxHeight="40"/>
<TextBlock Text="{Binding Subtitle}" Style="{StaticResource CaptionTextStyle}" TextWrapping="NoWrap"/>
</StackPanel>
</Grid>
</DataTemplate>
<!-- Grid-appropriate 300 by 70 pixel item template as seen in the SearchResultsPage -->
<DataTemplate x:Key="StandardSmallIcon300x70ItemTemplate">
<Grid Width="300">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Border Background="{StaticResource ListViewItemPlaceholderBackgroundThemeBrush}" Margin="10,10,0,20" Width="40" Height="40">
<Image Source="{Binding Image}" Stretch="UniformToFill"/>
</Border>
<StackPanel Grid.Column="1" Margin="10,0,10,10">
<TextBlock Text="{Binding Title}" Style="{StaticResource BodyTextStyle}" TextWrapping="NoWrap"/>
<TextBlock Text="{Binding Subtitle}" Style="{StaticResource BodyTextStyle}" Foreground="{StaticResource ApplicationSecondaryForegroundThemeBrush}" Height="40"/>
</StackPanel>
</Grid>
</DataTemplate>
<!-- List-appropriate 70 pixel high item template as seen in the SearchResultsPage when Snapped -->
<DataTemplate x:Key="StandardSmallIcon70ItemTemplate">
<Grid Margin="6">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Border Background="{StaticResource ListViewItemPlaceholderBackgroundThemeBrush}" Margin="0,0,0,10" Width="40" Height="40">
<Image Source="{Binding Image}" Stretch="UniformToFill"/>
</Border>
<StackPanel Grid.Column="1" Margin="10,-10,0,0">
<TextBlock Text="{Binding Title}" Style="{StaticResource BodyTextStyle}" TextWrapping="NoWrap"/>
<TextBlock Text="{Binding Subtitle}" Style="{StaticResource BodyTextStyle}" Foreground="{StaticResource ApplicationSecondaryForegroundThemeBrush}" Height="40"/>
</StackPanel>
</Grid>
</DataTemplate>
<!--
190x130 pixel item template for displaying file previews as seen in the FileOpenPickerPage
Includes an elaborate tooltip to display title and description text
-->
<DataTemplate x:Key="StandardFileWithTooltip190x130ItemTemplate">
<Grid>
<Grid Background="{StaticResource ListViewItemPlaceholderBackgroundThemeBrush}">
<Image
Source="{Binding Image}"
Width="190"
Height="130"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Stretch="Uniform"/>
</Grid>
<ToolTipService.Placement>Mouse</ToolTipService.Placement>
<ToolTipService.ToolTip>
<Grid Background="{StaticResource ApplicationPageBackgroundThemeBrush}">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Grid Background="{StaticResource ListViewItemPlaceholderBackgroundThemeBrush}" Margin="20">
<Image
Source="{Binding Image}"
Width="160"
Height="160"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Stretch="Uniform"/>
</Grid>
<StackPanel Width="200" Grid.Column="1" Margin="0,20,20,20">
<TextBlock Text="{Binding Title}" TextWrapping="NoWrap" Style="{StaticResource BodyTextStyle}"/>
<TextBlock Text="{Binding Description}" MaxHeight="140" Foreground="{StaticResource ApplicationSecondaryForegroundThemeBrush}" Style="{StaticResource BodyTextStyle}"/>
</StackPanel>
</Grid>
</ToolTipService.ToolTip>
</Grid>
</DataTemplate>
<!-- Default to 10-pixel spacing between grid items (after accounting for 4-pixel insets for focus) -->
<Style TargetType="GridViewItem">
<Setter Property="Margin" Value="0,0,2,2" />
</Style>
<!-- ScrollViewer styles -->
<Style x:Key="HorizontalScrollViewerStyle" TargetType="ScrollViewer">
<Setter Property="HorizontalScrollBarVisibility" Value="Auto"/>
<Setter Property="VerticalScrollBarVisibility" Value="Disabled"/>
<Setter Property="ScrollViewer.HorizontalScrollMode" Value="Enabled" />
<Setter Property="ScrollViewer.VerticalScrollMode" Value="Disabled" />
<Setter Property="ScrollViewer.ZoomMode" Value="Disabled" />
</Style>
<Style x:Key="VerticalScrollViewerStyle" TargetType="ScrollViewer">
<Setter Property="HorizontalScrollBarVisibility" Value="Disabled"/>
<Setter Property="VerticalScrollBarVisibility" Value="Auto"/>
<Setter Property="ScrollViewer.HorizontalScrollMode" Value="Disabled" />
<Setter Property="ScrollViewer.VerticalScrollMode" Value="Enabled" />
<Setter Property="ScrollViewer.ZoomMode" Value="Disabled" />
</Style>
<!-- Page layout roots typically use entrance animations and a theme-appropriate background color -->
<Style x:Key="LayoutRootStyle" TargetType="Panel">
<Setter Property="Background" Value="{StaticResource ApplicationPageBackgroundThemeBrush}"/>
<Setter Property="ChildrenTransitions">
<Setter.Value>
<TransitionCollection>
<EntranceThemeTransition/>
</TransitionCollection>
</Setter.Value>
</Setter>
</Style>
</ResourceDictionary>

View File

@ -0,0 +1,481 @@
//*********************************************************
//
// Copyright (c) Microsoft. All rights reserved.
// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
//
//*********************************************************
//
// SuspensionManager.cpp
// Implementation of the SuspensionManager class
//
#include "pch.h"
#include "SuspensionManager.h"
#include <collection.h>
#include <algorithm>
using namespace SDKSample::Common;
using namespace Concurrency;
using namespace Platform;
using namespace Platform::Collections;
using namespace Windows::Foundation;
using namespace Windows::Foundation::Collections;
using namespace Windows::Storage;
using namespace Windows::Storage::FileProperties;
using namespace Windows::Storage::Streams;
using namespace Windows::UI::Xaml;
using namespace Windows::UI::Xaml::Controls;
using namespace Windows::UI::Xaml::Interop;
namespace
{
Map<String^, Object^>^ _sessionState = ref new Map<String^, Object^>();
String^ sessionStateFilename = "_sessionState.dat";
// Forward declarations for object object read / write support
void WriteObject(Windows::Storage::Streams::DataWriter^ writer, Platform::Object^ object);
Platform::Object^ ReadObject(Windows::Storage::Streams::DataReader^ reader);
}
/// <summary>
/// Provides access to global session state for the current session. This state is serialized by
/// <see cref="SaveAsync"/> and restored by <see cref="RestoreAsync"/> which require values to be
/// one of the following: boxed values including integers, floating-point singles and doubles,
/// wide characters, boolean, Strings and Guids, or Map<String^, Object^> where map values are
/// subject to the same constraints. Session state should be as compact as possible.
/// </summary>
IMap<String^, Object^>^ SuspensionManager::SessionState::get(void)
{
return _sessionState;
}
/// <summary>
/// Wrap a WeakReference as a reference object for use in a collection.
/// </summary>
private ref class WeakFrame sealed
{
private:
WeakReference _frameReference;
internal:
WeakFrame(Frame^ frame) { _frameReference = frame; }
property Frame^ ResolvedFrame
{
Frame^ get(void) { return _frameReference.Resolve<Frame>(); }
};
};
namespace
{
std::vector<WeakFrame^> _registeredFrames;
DependencyProperty^ FrameSessionStateKeyProperty =
DependencyProperty::RegisterAttached("_FrameSessionStateKeyProperty",
TypeName(String::typeid), TypeName(SuspensionManager::typeid), nullptr);
DependencyProperty^ FrameSessionStateProperty =
DependencyProperty::RegisterAttached("_FrameSessionStateProperty",
TypeName(IMap<String^, Object^>::typeid), TypeName(SuspensionManager::typeid), nullptr);
}
/// <summary>
/// Registers a <see cref="Frame"/> instance to allow its navigation history to be saved to
/// and restored from <see cref="SessionState"/>. Frames should be registered once
/// immediately after creation if they will participate in session state management. Upon
/// registration if state has already been restored for the specified key
/// the navigation history will immediately be restored. Subsequent invocations of
/// <see cref="RestoreAsync(String)"/> will also restore navigation history.
/// </summary>
/// <param name="frame">An instance whose navigation history should be managed by
/// <see cref="SuspensionManager"/></param>
/// <param name="sessionStateKey">A unique key into <see cref="SessionState"/> used to
/// store navigation-related information.</param>
void SuspensionManager::RegisterFrame(Frame^ frame, String^ sessionStateKey)
{
if (frame->GetValue(FrameSessionStateKeyProperty) != nullptr)
{
throw ref new FailureException("Frames can only be registered to one session state key");
}
if (frame->GetValue(FrameSessionStateProperty) != nullptr)
{
throw ref new FailureException("Frames must be either be registered before accessing frame session state, or not registered at all");
}
// Use a dependency property to associate the session key with a frame, and keep a list of frames whose
// navigation state should be managed
frame->SetValue(FrameSessionStateKeyProperty, sessionStateKey);
_registeredFrames.insert(_registeredFrames.begin(), ref new WeakFrame(frame));
// Check to see if navigation state can be restored
RestoreFrameNavigationState(frame);
}
/// <summary>
/// Disassociates a <see cref="Frame"/> previously registered by <see cref="RegisterFrame"/>
/// from <see cref="SessionState"/>. Any navigation state previously captured will be
/// removed.
/// </summary>
/// <param name="frame">An instance whose navigation history should no longer be
/// managed.</param>
void SuspensionManager::UnregisterFrame(Frame^ frame)
{
// Remove session state and remove the frame from the list of frames whose navigation
// state will be saved (along with any weak references that are no longer reachable)
auto key = safe_cast<String^>(frame->GetValue(FrameSessionStateKeyProperty));
if (SessionState->HasKey(key)) SessionState->Remove(key);
_registeredFrames.erase(
std::remove_if(_registeredFrames.begin(), _registeredFrames.end(), [=](WeakFrame^& e)
{
auto testFrame = e->ResolvedFrame;
return testFrame == nullptr || testFrame == frame;
}),
_registeredFrames.end()
);
}
/// <summary>
/// Provides storage for session state associated with the specified <see cref="Frame"/>.
/// Frames that have been previously registered with <see cref="RegisterFrame"/> have
/// their session state saved and restored automatically as a part of the global
/// <see cref="SessionState"/>. Frames that are not registered have transient state
/// that can still be useful when restoring pages that have been discarded from the
/// navigation cache.
/// </summary>
/// <remarks>Apps may choose to rely on <see cref="LayoutAwarePage"/> to manage
/// page-specific state instead of working with frame session state directly.</remarks>
/// <param name="frame">The instance for which session state is desired.</param>
/// <returns>A collection of state subject to the same serialization mechanism as
/// <see cref="SessionState"/>.</returns>
IMap<String^, Object^>^ SuspensionManager::SessionStateForFrame(Frame^ frame)
{
auto frameState = safe_cast<IMap<String^, Object^>^>(frame->GetValue(FrameSessionStateProperty));
if (frameState == nullptr)
{
auto frameSessionKey = safe_cast<String^>(frame->GetValue(FrameSessionStateKeyProperty));
if (frameSessionKey != nullptr)
{
// Registered frames reflect the corresponding session state
if (!_sessionState->HasKey(frameSessionKey))
{
_sessionState->Insert(frameSessionKey, ref new Map<String^, Object^>());
}
frameState = safe_cast<IMap<String^, Object^>^>(_sessionState->Lookup(frameSessionKey));
}
else
{
// Frames that aren't registered have transient state
frameState = ref new Map<String^, Object^>();
}
frame->SetValue(FrameSessionStateProperty, frameState);
}
return frameState;
}
void SuspensionManager::RestoreFrameNavigationState(Frame^ frame)
{
auto frameState = SessionStateForFrame(frame);
if (frameState->HasKey("Navigation"))
{
frame->SetNavigationState(safe_cast<String^>(frameState->Lookup("Navigation")));
}
}
void SuspensionManager::SaveFrameNavigationState(Frame^ frame)
{
auto frameState = SessionStateForFrame(frame);
frameState->Insert("Navigation", frame->GetNavigationState());
}
/// <summary>
/// Save the current <see cref="SessionState"/>. Any <see cref="Frame"/> instances
/// registered with <see cref="RegisterFrame"/> will also preserve their current
/// navigation stack, which in turn gives their active <see cref="Page"/> an opportunity
/// to save its state.
/// </summary>
/// <returns>An asynchronous task that reflects when session state has been saved.</returns>
task<void> SuspensionManager::SaveAsync(void)
{
// Save the navigation state for all registered frames
for (auto&& weakFrame : _registeredFrames)
{
auto frame = weakFrame->ResolvedFrame;
if (frame != nullptr) SaveFrameNavigationState(frame);
}
// Serialize the session state synchronously to avoid asynchronous access to shared
// state
auto sessionData = ref new InMemoryRandomAccessStream();
auto sessionDataWriter = ref new DataWriter(sessionData->GetOutputStreamAt(0));
WriteObject(sessionDataWriter, _sessionState);
// Once session state has been captured synchronously, begin the asynchronous process
// of writing the result to disk
return task<unsigned int>(sessionDataWriter->StoreAsync()).then([=](unsigned int)
{
return sessionDataWriter->FlushAsync();
}).then([=](bool flushSucceeded)
{
(void)flushSucceeded; // Unused parameter
return ApplicationData::Current->LocalFolder->CreateFileAsync(sessionStateFilename,
CreationCollisionOption::ReplaceExisting);
}).then([=](StorageFile^ createdFile)
{
return createdFile->OpenAsync(FileAccessMode::ReadWrite);
}).then([=](IRandomAccessStream^ newStream)
{
return RandomAccessStream::CopyAndCloseAsync(
sessionData->GetInputStreamAt(0), newStream->GetOutputStreamAt(0));
}).then([=](UINT64 copiedBytes)
{
(void)copiedBytes; // Unused parameter
return;
});
}
/// <summary>
/// Restores previously saved <see cref="SessionState"/>. Any <see cref="Frame"/> instances
/// registered with <see cref="RegisterFrame"/> will also restore their prior navigation
/// state, which in turn gives their active <see cref="Page"/> an opportunity restore its
/// state.
/// </summary>
/// <param name="version">A version identifier compared to the session state to prevent
/// incompatible versions of session state from reaching app code. Saved state with a
/// different version will be ignored, resulting in an empty <see cref="SessionState"/>
/// dictionary.</param>
/// <returns>An asynchronous task that reflects when session state has been read. The
/// content of <see cref="SessionState"/> should not be relied upon until this task
/// completes.</returns>
task<void> SuspensionManager::RestoreAsync(void)
{
_sessionState->Clear();
task<StorageFile^> getFileTask(ApplicationData::Current->LocalFolder->GetFileAsync(sessionStateFilename));
return getFileTask.then([=](StorageFile^ stateFile)
{
task<BasicProperties^> getBasicPropertiesTask(stateFile->GetBasicPropertiesAsync());
return getBasicPropertiesTask.then([=](BasicProperties^ stateFileProperties)
{
auto size = unsigned int(stateFileProperties->Size);
if (size != stateFileProperties->Size) throw ref new FailureException("Session state larger than 4GB");
task<IRandomAccessStreamWithContentType^> openReadTask(stateFile->OpenReadAsync());
return openReadTask.then([=](IRandomAccessStreamWithContentType^ stateFileStream)
{
auto stateReader = ref new DataReader(stateFileStream);
return task<unsigned int>(stateReader->LoadAsync(size)).then([=](unsigned int bytesRead)
{
(void)bytesRead; // Unused parameter
// Deserialize the Session State
Object^ content = ReadObject(stateReader);
_sessionState = (Map<String^, Object^>^)content;
// Restore any registered frames to their saved state
for (auto&& weakFrame : _registeredFrames)
{
auto frame = weakFrame->ResolvedFrame;
if (frame != nullptr)
{
frame->ClearValue(FrameSessionStateProperty);
RestoreFrameNavigationState(frame);
}
}
}, task_continuation_context::use_current());
});
});
});
}
#pragma region Object serialization for a known set of types
namespace
{
// Codes used for identifying serialized types
enum StreamTypes {
NullPtrType = 0,
// Supported IPropertyValue types
UInt8Type, UInt16Type, UInt32Type, UInt64Type, Int16Type, Int32Type, Int64Type,
SingleType, DoubleType, BooleanType, Char16Type, GuidType, StringType,
// Additional supported types
StringToObjectMapType,
// Marker values used to ensure stream integrity
MapEndMarker
};
void WriteString(DataWriter^ writer, String^ string)
{
writer->WriteByte(StringType);
writer->WriteUInt32(writer->MeasureString(string));
writer->WriteString(string);
}
void WriteProperty(DataWriter^ writer, IPropertyValue^ propertyValue)
{
switch (propertyValue->Type)
{
case PropertyType::UInt8:
writer->WriteByte(UInt8Type);
writer->WriteByte(propertyValue->GetUInt8());
return;
case PropertyType::UInt16:
writer->WriteByte(UInt16Type);
writer->WriteUInt16(propertyValue->GetUInt16());
return;
case PropertyType::UInt32:
writer->WriteByte(UInt32Type);
writer->WriteUInt32(propertyValue->GetUInt32());
return;
case PropertyType::UInt64:
writer->WriteByte(UInt64Type);
writer->WriteUInt64(propertyValue->GetUInt64());
return;
case PropertyType::Int16:
writer->WriteByte(Int16Type);
writer->WriteUInt16(propertyValue->GetInt16());
return;
case PropertyType::Int32:
writer->WriteByte(Int32Type);
writer->WriteUInt32(propertyValue->GetInt32());
return;
case PropertyType::Int64:
writer->WriteByte(Int64Type);
writer->WriteUInt64(propertyValue->GetInt64());
return;
case PropertyType::Single:
writer->WriteByte(SingleType);
writer->WriteSingle(propertyValue->GetSingle());
return;
case PropertyType::Double:
writer->WriteByte(DoubleType);
writer->WriteDouble(propertyValue->GetDouble());
return;
case PropertyType::Boolean:
writer->WriteByte(BooleanType);
writer->WriteBoolean(propertyValue->GetBoolean());
return;
case PropertyType::Char16:
writer->WriteByte(Char16Type);
writer->WriteUInt16(propertyValue->GetChar16());
return;
case PropertyType::Guid:
writer->WriteByte(GuidType);
writer->WriteGuid(propertyValue->GetGuid());
return;
case PropertyType::String:
WriteString(writer, propertyValue->GetString());
return;
default:
throw ref new InvalidArgumentException("Unsupported property type");
}
}
void WriteStringToObjectMap(DataWriter^ writer, IMap<String^, Object^>^ map)
{
writer->WriteByte(StringToObjectMapType);
writer->WriteUInt32(map->Size);
for (auto&& pair : map)
{
WriteObject(writer, pair->Key);
WriteObject(writer, pair->Value);
}
writer->WriteByte(MapEndMarker);
}
void WriteObject(DataWriter^ writer, Object^ object)
{
if (object == nullptr)
{
writer->WriteByte(NullPtrType);
return;
}
auto propertyObject = dynamic_cast<IPropertyValue^>(object);
if (propertyObject != nullptr)
{
WriteProperty(writer, propertyObject);
return;
}
auto mapObject = dynamic_cast<IMap<String^, Object^>^>(object);
if (mapObject != nullptr)
{
WriteStringToObjectMap(writer, mapObject);
return;
}
throw ref new InvalidArgumentException("Unsupported data type");
}
String^ ReadString(DataReader^ reader)
{
int length = reader->ReadUInt32();
String^ string = reader->ReadString(length);
return string;
}
IMap<String^, Object^>^ ReadStringToObjectMap(DataReader^ reader)
{
auto map = ref new Map<String^, Object^>();
auto size = reader->ReadUInt32();
for (unsigned int index = 0; index < size; index++)
{
auto key = safe_cast<String^>(ReadObject(reader));
auto value = ReadObject(reader);
map->Insert(key, value);
}
if (reader->ReadByte() != MapEndMarker)
{
throw ref new InvalidArgumentException("Invalid stream");
}
return map;
}
Object^ ReadObject(DataReader^ reader)
{
auto type = reader->ReadByte();
switch (type)
{
case NullPtrType:
return nullptr;
case UInt8Type:
return reader->ReadByte();
case UInt16Type:
return reader->ReadUInt16();
case UInt32Type:
return reader->ReadUInt32();
case UInt64Type:
return reader->ReadUInt64();
case Int16Type:
return reader->ReadInt16();
case Int32Type:
return reader->ReadInt32();
case Int64Type:
return reader->ReadInt64();
case SingleType:
return reader->ReadSingle();
case DoubleType:
return reader->ReadDouble();
case BooleanType:
return reader->ReadBoolean();
case Char16Type:
return (char16_t)reader->ReadUInt16();
case GuidType:
return reader->ReadGuid();
case StringType:
return ReadString(reader);
case StringToObjectMapType:
return ReadStringToObjectMap(reader);
default:
throw ref new InvalidArgumentException("Unsupported property type");
}
}
}
#pragma endregion

View File

@ -0,0 +1,50 @@
//*********************************************************
//
// Copyright (c) Microsoft. All rights reserved.
// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
//
//*********************************************************
//
// SuspensionManager.h
// Declaration of the SuspensionManager class
//
#pragma once
#include <ppltasks.h>
namespace SDKSample
{
namespace Common
{
/// <summary>
/// SuspensionManager captures global session state to simplify process lifetime management
/// for an application. Note that session state will be automatically cleared under a variety
/// of conditions and should only be used to store information that would be convenient to
/// carry across sessions, but that should be disacarded when an application crashes or is
/// upgraded.
/// </summary>
ref class SuspensionManager sealed
{
internal:
static void RegisterFrame(Windows::UI::Xaml::Controls::Frame^ frame, Platform::String^ sessionStateKey);
static void UnregisterFrame(Windows::UI::Xaml::Controls::Frame^ frame);
static Concurrency::task<void> SaveAsync(void);
static Concurrency::task<void> RestoreAsync(void);
static property Windows::Foundation::Collections::IMap<Platform::String^, Platform::Object^>^ SessionState
{
Windows::Foundation::Collections::IMap<Platform::String^, Platform::Object^>^ get(void);
};
static Windows::Foundation::Collections::IMap<Platform::String^, Platform::Object^>^ SessionStateForFrame(
Windows::UI::Xaml::Controls::Frame^ frame);
private:
static void RestoreFrameNavigationState(Windows::UI::Xaml::Controls::Frame^ frame);
static void SaveFrameNavigationState(Windows::UI::Xaml::Controls::Frame^ frame);
};
}
}