Browse files

Winrt mvvm example

  • Loading branch information...
1 parent 4aa8810 commit 2c14492f6b389088c5741829f67db14a5a8f6bb4 @mikoskinen committed Mar 12, 2012
View
22 WinRT-MVVM-Example/App.xaml
@@ -0,0 +1,22 @@
+<Application
+ x:Class="Application6.App"
+ xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
+ xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+ xmlns:local="using:Application6">
+
+ <Application.Resources>
+ <ResourceDictionary>
+ <ResourceDictionary.MergedDictionaries>
+
+ <!--
+ Styles that define common aspects of the platform look and feel
+ Required by Visual Studio project and item templates
+ -->
+ <ResourceDictionary Source="Common/StandardStyles.xaml"/>
+ </ResourceDictionary.MergedDictionaries>
+
+ <local:ViewModelLocator x:Key="ViewModelLocator"/>
+
+ </ResourceDictionary>
+ </Application.Resources>
+</Application>
View
75 WinRT-MVVM-Example/App.xaml.cs
@@ -0,0 +1,75 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using Windows.ApplicationModel;
+using Windows.ApplicationModel.Activation;
+using Windows.Foundation;
+using Windows.Foundation.Collections;
+using Windows.UI.Xaml;
+using Windows.UI.Xaml.Controls;
+using Windows.UI.Xaml.Controls.Primitives;
+using Windows.UI.Xaml.Data;
+using Windows.UI.Xaml.Input;
+using Windows.UI.Xaml.Media;
+using Windows.UI.Xaml.Navigation;
+
+// The Blank Application template is documented at http://go.microsoft.com/fwlink/?LinkId=234227
+
+namespace Application6
+{
+
+ /// <summary>
+ /// Provides application-specific behavior to supplement the default Application class.
+ /// </summary>
+ sealed partial class App : Application
+ {
+ public static NavigationService NavigationService;
+
+ /// <summary>
+ /// Initializes the singleton application object. This is the first line of authored code
+ /// executed, and as such is the logical equivalent of main() or WinMain().
+ /// </summary>
+ public App()
+ {
+ this.InitializeComponent();
+ this.Suspending += OnSuspending;
+ }
+
+ /// <summary>
+ /// Invoked when the application is launched normally by the end user. Other entry points
+ /// will be used when the application is launched to open a specific file, to display
+ /// search results, and so forth.
+ /// </summary>
+ /// <param name="args">Details about the launch request and process.</param>
+ protected override void OnLaunched(LaunchActivatedEventArgs args)
+ {
+ if (args.PreviousExecutionState == ApplicationExecutionState.Terminated)
+ {
+ //TODO: Load state from previously suspended application
+ }
+
+ // Create a Frame to act navigation context and navigate to the first page
+ var rootFrame = new Frame();
+ App.NavigationService = new NavigationService(rootFrame);
+
+ rootFrame.Navigate(typeof(BlankPage));
+
+ // Place the frame in the current Window and ensure that it is active
+ Window.Current.Content = rootFrame;
+ Window.Current.Activate();
+ }
+
+ /// <summary>
+ /// Invoked when application execution is being suspended. Application state is saved
+ /// without knowing whether the application will be terminated or resumed with the contents
+ /// of memory still intact.
+ /// </summary>
+ /// <param name="sender">The source of the suspend request.</param>
+ /// <param name="e">Details about the suspend request.</param>
+ void OnSuspending(object sender, SuspendingEventArgs e)
+ {
+ //TODO: Save application state and stop any background activity
+ }
+ }
+}
View
BIN WinRT-MVVM-Example/Application6_TemporaryKey.pfx
Binary file not shown.
View
BIN WinRT-MVVM-Example/Assets/Logo.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
View
BIN WinRT-MVVM-Example/Assets/SmallLogo.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
View
BIN WinRT-MVVM-Example/Assets/SplashScreen.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
View
BIN WinRT-MVVM-Example/Assets/StoreLogo.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
View
15 WinRT-MVVM-Example/BlankPage.xaml
@@ -0,0 +1,15 @@
+<Page
+ x:Class="Application6.BlankPage"
+ xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
+ xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+ xmlns:local="using:Application6"
+ xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
+ xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
+ DataContext="{Binding BlankPageViewModel, Source={StaticResource ViewModelLocator}}"
+ mc:Ignorable="d">
+
+ <Grid Background="{StaticResource ApplicationPageBackgroundBrush}">
+ <TextBlock Text="First page" HorizontalAlignment="Center" VerticalAlignment="Top" Style="{StaticResource PageHeaderTextStyle}" />
+ <Button Content="Navigate forward" Command="{Binding GoToNextPage}"/>
+ </Grid>
+</Page>
View
38 WinRT-MVVM-Example/BlankPage.xaml.cs
@@ -0,0 +1,38 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using Windows.Foundation;
+using Windows.Foundation.Collections;
+using Windows.UI.Xaml;
+using Windows.UI.Xaml.Controls;
+using Windows.UI.Xaml.Controls.Primitives;
+using Windows.UI.Xaml.Data;
+using Windows.UI.Xaml.Input;
+using Windows.UI.Xaml.Media;
+using Windows.UI.Xaml.Navigation;
+
+// The Blank Page item template is documented at http://go.microsoft.com/fwlink/?LinkId=234238
+
+namespace Application6
+{
+ /// <summary>
+ /// An empty page that can be used on its own or navigated to within a Frame.
+ /// </summary>
+ public sealed partial class BlankPage : Page
+ {
+ public BlankPage()
+ {
+ this.InitializeComponent();
+ }
+
+ /// <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 is typically used to configure the page.</param>
+ protected override void OnNavigatedTo(NavigationEventArgs e)
+ {
+ }
+ }
+}
View
26 WinRT-MVVM-Example/BlankPageViewModel.cs
@@ -0,0 +1,26 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Application6
+{
+ public class BlankPageViewModel
+ {
+ private readonly NavigationService navigation;
+
+ public BlankPageViewModel(NavigationService navigation)
+ {
+ this.navigation = navigation;
+ }
+
+ public DelegateCommand GoToNextPage
+ {
+ get
+ {
+ return new DelegateCommand(x => navigation.Navigate<SecondPage>(), x => true);
+ }
+ }
+ }
+}
View
55 WinRT-MVVM-Example/Common/BindableBase.cs
@@ -0,0 +1,55 @@
+using System;
+using System.ComponentModel;
+using System.Runtime.CompilerServices;
+using Windows.UI.Xaml.Data;
+
+namespace Application6.Common
+{
+ /// <summary>
+ /// Implementation of <see cref="INotifyPropertyChanged"/> to simplify models.
+ /// </summary>
+ [Windows.Foundation.Metadata.WebHostHidden]
+ public abstract class BindableBase : INotifyPropertyChanged
+ {
+ /// <summary>
+ /// Multicast event for property change notifications.
+ /// </summary>
+ public event PropertyChangedEventHandler PropertyChanged;
+
+ /// <summary>
+ /// Checks if a property already matches a desired value. Sets the property and
+ /// notifies listeners only when necessary.
+ /// </summary>
+ /// <typeparam name="T">Type of the property.</typeparam>
+ /// <param name="storage">Reference to a property with both getter and setter.</param>
+ /// <param name="value">Desired value for the property.</param>
+ /// <param name="propertyName">Name of the property used to notify listeners. This
+ /// value is optional and can be provided automatically when invoked from compilers that
+ /// support CallerMemberName.</param>
+ /// <returns>True if the value was changed, false if the existing value matched the
+ /// desired value.</returns>
+ protected bool SetProperty<T>(ref T storage, T value, [CallerMemberName] String propertyName = null)
+ {
+ if (object.Equals(storage, value)) return false;
+
+ storage = value;
+ this.OnPropertyChanged(propertyName);
+ return true;
+ }
+
+ /// <summary>
+ /// Notifies listeners that a property value has changed.
+ /// </summary>
+ /// <param name="propertyName">Name of the property used to notify listeners. This
+ /// value is optional and can be provided automatically when invoked from compilers
+ /// that support <see cref="CallerMemberNameAttribute"/>.</param>
+ protected void OnPropertyChanged([CallerMemberName] string propertyName = null)
+ {
+ var eventHandler = this.PropertyChanged;
+ if (eventHandler != null)
+ {
+ eventHandler(this, new PropertyChangedEventArgs(propertyName));
+ }
+ }
+ }
+}
View
21 WinRT-MVVM-Example/Common/BooleanNegationConverter.cs
@@ -0,0 +1,21 @@
+using System;
+using Windows.UI.Xaml.Data;
+
+namespace Application6.Common
+{
+ /// <summary>
+ /// Value converter that translates true to false and vice versa.
+ /// </summary>
+ public sealed class BooleanNegationConverter : IValueConverter
+ {
+ public object Convert(object value, Type targetType, object parameter, string language)
+ {
+ return !(value is bool && (bool)value);
+ }
+
+ public object ConvertBack(object value, Type targetType, object parameter, string language)
+ {
+ return !(value is bool && (bool)value);
+ }
+ }
+}
View
32 WinRT-MVVM-Example/Common/BooleanToVisibilityConverter.cs
@@ -0,0 +1,32 @@
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Linq;
+using System.Runtime.CompilerServices;
+using Windows.Foundation;
+using Windows.Foundation.Collections;
+using Windows.Graphics.Display;
+using Windows.UI.ViewManagement;
+using Windows.UI.Xaml;
+using Windows.UI.Xaml.Controls;
+using Windows.UI.Xaml.Data;
+
+namespace Application6.Common
+{
+ /// <summary>
+ /// Value converter that translates true to <see cref="Visibility.Visible"/> and false to
+ /// <see cref="Visibility.Collapsed"/>.
+ /// </summary>
+ public sealed class BooleanToVisibilityConverter : IValueConverter
+ {
+ public object Convert(object value, Type targetType, object parameter, string language)
+ {
+ return (value is bool && (bool)value) ? Visibility.Visible : Visibility.Collapsed;
+ }
+
+ public object ConvertBack(object value, Type targetType, object parameter, string language)
+ {
+ return value is Visibility && (Visibility)value == Visibility.Visible;
+ }
+ }
+}
View
365 WinRT-MVVM-Example/Common/LayoutAwarePage.cs
@@ -0,0 +1,365 @@
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Linq;
+using Windows.Foundation;
+using Windows.Foundation.Collections;
+using Windows.UI.ViewManagement;
+using Windows.UI.Xaml;
+using Windows.UI.Xaml.Controls;
+
+namespace Application6.Common
+{
+ /// <summary>
+ /// Typical implementation of Page that provides several important conveniences:
+ /// application view state to visual state mapping, GoBack and GoHome event handlers, and
+ /// a default view model.
+ /// </summary>
+ [Windows.Foundation.Metadata.WebHostHidden]
+ public class LayoutAwarePage : Page
+ {
+ private List<Control> _layoutAwareControls;
+ private IObservableMap<String, Object> _defaultViewModel = new ObservableDictionary<String, Object>();
+ private bool _useFilledStateForNarrowWindow = false;
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="LayoutAwarePage"/> class.
+ /// </summary>
+ public LayoutAwarePage()
+ {
+ if (Windows.ApplicationModel.DesignMode.DesignModeEnabled) return;
+
+ // Map application view state to visual state for this page when it is part of the visual tree
+ this.Loaded += this.StartLayoutUpdates;
+ this.Unloaded += this.StopLayoutUpdates;
+
+ // Establish the default view model as the initial DataContext
+ this.DataContext = _defaultViewModel;
+ }
+
+ /// <summary>
+ /// Gets an implementation of <see cref="IObservableMap<String, Object>"/> set as the
+ /// page's default <see cref="DataContext"/>. This instance can be bound and surfaces
+ /// property change notifications making it suitable for use as a trivial view model.
+ /// </summary>
+ protected IObservableMap<String, Object> DefaultViewModel
+ {
+ get
+ {
+ return _defaultViewModel;
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets a value indicating whether visual states can be a loose interpretation
+ /// of the actual application view state. This is often convenient when a page layout
+ /// is space constrained.
+ /// </summary>
+ /// <remarks>
+ /// The default value of false indicates that the visual state is identical to the view
+ /// state, meaning that Filled is only used when another application is snapped. When
+ /// set to true FullScreenLandscape is used to indicate that at least 1366 virtual
+ /// pixels of horizontal real estate are available - even if another application is
+ /// snapped - and Filled indicates a lesser width, even if no other application is
+ /// snapped. On a smaller display such as a 1024x768 panel this will result in the
+ /// visual state Filled whenever the device is in landscape orientation.
+ /// </remarks>
+ public bool UseFilledStateForNarrowWindow
+ {
+ get
+ {
+ return _useFilledStateForNarrowWindow;
+ }
+
+ set
+ {
+ _useFilledStateForNarrowWindow = value;
+ this.InvalidateVisualState();
+ }
+ }
+
+ /// <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>
+ protected virtual void GoHome(object sender, RoutedEventArgs e)
+ {
+ // Use the navigation frame to return to the topmost page
+ if (this.Frame != null)
+ {
+ while (this.Frame.CanGoBack) this.Frame.GoBack();
+ }
+ }
+
+ /// <summary>
+ /// Invoked as an event handler to navigate backward in the page's associated
+ /// <see cref="Frame"/> to go back one step on 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>
+ protected virtual void GoBack(object sender, RoutedEventArgs e)
+ {
+ // Use the navigation frame to return to the previous page
+ if (this.Frame != null && this.Frame.CanGoBack) this.Frame.GoBack();
+ }
+
+ /// <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"/>
+ public void StartLayoutUpdates(object sender, RoutedEventArgs e)
+ {
+ var control = sender as Control;
+ if (control == null) return;
+ if (this._layoutAwareControls == null)
+ {
+ // Start listening to view state changes when there are controls interested in updates
+ ApplicationView.GetForCurrentView().ViewStateChanged += this.ViewStateChanged;
+ Window.Current.SizeChanged += this.WindowSizeChanged;
+ this._layoutAwareControls = new List<Control>();
+ }
+ this._layoutAwareControls.Add(control);
+
+ // Set the initial visual state of the control
+ VisualStateManager.GoToState(control, DetermineVisualState(ApplicationView.Value), false);
+ }
+
+ private void ViewStateChanged(ApplicationView sender, ApplicationViewStateChangedEventArgs e)
+ {
+ this.InvalidateVisualState(e.ViewState);
+ }
+
+ private void WindowSizeChanged(object sender, Windows.UI.Core.WindowSizeChangedEventArgs e)
+ {
+ if (this._useFilledStateForNarrowWindow) this.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"/>
+ public void StopLayoutUpdates(object sender, RoutedEventArgs e)
+ {
+ var control = sender as Control;
+ if (control == null || this._layoutAwareControls == null) return;
+ this._layoutAwareControls.Remove(control);
+ if (this._layoutAwareControls.Count == 0)
+ {
+ // Stop listening to view state changes when no controls are interested in updates
+ this._layoutAwareControls = null;
+ ApplicationView.GetForCurrentView().ViewStateChanged -= this.ViewStateChanged;
+ Window.Current.SizeChanged -= this.WindowSizeChanged;
+ }
+ }
+
+ /// <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"/>
+ protected virtual string DetermineVisualState(ApplicationViewState viewState)
+ {
+ if (this._useFilledStateForNarrowWindow &&
+ (viewState == ApplicationViewState.Filled ||
+ viewState == ApplicationViewState.FullScreenLandscape))
+ {
+ // Allow pages to request that the Filled state be used only for landscape layouts narrower
+ // than 1366 virtual pixels
+ var windowWidth = Window.Current.Bounds.Width;
+ viewState = windowWidth >= 1366 ? ApplicationViewState.FullScreenLandscape : ApplicationViewState.Filled;
+ }
+ return viewState.ToString();
+ }
+
+ /// <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>
+ /// <param name="viewState">The desired view state, or null if the current view state
+ /// should be used.</param>
+ public void InvalidateVisualState(ApplicationViewState? viewState = null)
+ {
+ if (this._layoutAwareControls != null)
+ {
+ string visualState = DetermineVisualState(viewState == null ? ApplicationView.Value : viewState.Value);
+ foreach (var layoutAwareControl in this._layoutAwareControls)
+ {
+ VisualStateManager.GoToState(layoutAwareControl, visualState, false);
+ }
+ }
+ }
+
+ /// <summary>
+ /// Implementation of IObservableMap that supports reentrancy for use as a default view
+ /// model.
+ /// </summary>
+ private class ObservableDictionary<K, V> : IObservableMap<K, V>
+ {
+ private class ObservableDictionaryChangedEventArgs : IMapChangedEventArgs<K>
+ {
+ public ObservableDictionaryChangedEventArgs(CollectionChange change, K key)
+ {
+ this.CollectionChange = change;
+ this.Key = key;
+ }
+
+ public CollectionChange CollectionChange { get; private set; }
+ public K Key { get; private set; }
+ }
+
+ private Dictionary<K, V> _dictionary = new Dictionary<K, V>();
+ public event MapChangedEventHandler<K, V> MapChanged;
+
+ private void InvokeMapChanged(CollectionChange change, K key)
+ {
+ var eventHandler = MapChanged;
+ if (eventHandler != null)
+ {
+ eventHandler(this, new ObservableDictionaryChangedEventArgs(CollectionChange.ItemInserted, key));
+ }
+ }
+
+ public void Add(K key, V value)
+ {
+ this._dictionary.Add(key, value);
+ this.InvokeMapChanged(CollectionChange.ItemInserted, key);
+ }
+
+ public void Add(KeyValuePair<K, V> item)
+ {
+ this.Add(item.Key, item.Value);
+ }
+
+ public bool Remove(K key)
+ {
+ if (this._dictionary.Remove(key))
+ {
+ this.InvokeMapChanged(CollectionChange.ItemRemoved, key);
+ return true;
+ }
+ return false;
+ }
+
+ public bool Remove(KeyValuePair<K, V> item)
+ {
+ V currentValue;
+ if (this._dictionary.TryGetValue(item.Key, out currentValue) &&
+ Object.Equals(item.Value, currentValue) && this._dictionary.Remove(item.Key))
+ {
+ this.InvokeMapChanged(CollectionChange.ItemRemoved, item.Key);
+ return true;
+ }
+ return false;
+ }
+
+ public V this[K key]
+ {
+ get
+ {
+ return this._dictionary[key];
+ }
+ set
+ {
+ this._dictionary[key] = value;
+ this.InvokeMapChanged(CollectionChange.ItemChanged, key);
+ }
+ }
+
+ public void Clear()
+ {
+ var priorKeys = this._dictionary.Keys.ToArray();
+ this._dictionary.Clear();
+ foreach (var key in priorKeys)
+ {
+ this.InvokeMapChanged(CollectionChange.ItemRemoved, key);
+ }
+ }
+
+ public ICollection<K> Keys
+ {
+ get { return this._dictionary.Keys; }
+ }
+
+ public bool ContainsKey(K key)
+ {
+ return this._dictionary.ContainsKey(key);
+ }
+
+ public bool TryGetValue(K key, out V value)
+ {
+ return this._dictionary.TryGetValue(key, out value);
+ }
+
+ public ICollection<V> Values
+ {
+ get { return this._dictionary.Values; }
+ }
+
+ public bool Contains(KeyValuePair<K, V> item)
+ {
+ return this._dictionary.Contains(item);
+ }
+
+ public int Count
+ {
+ get { return this._dictionary.Count; }
+ }
+
+ public bool IsReadOnly
+ {
+ get { return false; }
+ }
+
+ public IEnumerator<KeyValuePair<K, V>> GetEnumerator()
+ {
+ return this._dictionary.GetEnumerator();
+ }
+
+ System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
+ {
+ return this._dictionary.GetEnumerator();
+ }
+
+ public void CopyTo(KeyValuePair<K, V>[] array, int arrayIndex)
+ {
+ int arraySize = array.Length;
+ foreach (var pair in this._dictionary)
+ {
+ if (arrayIndex >= arraySize) break;
+ array[arrayIndex++] = pair;
+ }
+ }
+ }
+ }
+}
View
7 WinRT-MVVM-Example/Common/ReadMe.txt
@@ -0,0 +1,7 @@
+The Common directory contains classes and XAML styles that simplify application development.
+
+These are not merely convenient, but are required by most Visual Studio project and item templates.
+Removing, renaming, or otherwise modifying the content of these files may result in a project that
+does not build, or that will not build once additional pages are added. If variations on these
+classes or styles are desired it is recommended that you copy the content under a new name and
+modify your private copy.
View
210 WinRT-MVVM-Example/Common/RichTextColumns.cs
@@ -0,0 +1,210 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading.Tasks;
+using Windows.Foundation;
+using Windows.UI.Xaml;
+using Windows.UI.Xaml.Controls;
+using Windows.UI.Xaml.Data;
+using Windows.UI.Xaml.Documents;
+
+namespace Application6.Common
+{
+ /// <summary>
+ /// Wrapper for <see cref="RichTextBlock"/> that creates as many additional overflow
+ /// columns as needed to fit the available content.
+ /// </summary>
+ /// <example>
+ /// The following creates a collection of 400-pixel wide columns spaced 50 pixels apart
+ /// to contain arbitrary data-bound content:
+ /// <code>
+ /// <RichTextColumns>
+ /// <RichTextColumns.ColumnTemplate>
+ /// <DataTemplate>
+ /// <RichTextBlockOverflow Width="400" Margin="50,0,0,0"/>
+ /// </DataTemplate>
+ /// </RichTextColumns.ColumnTemplate>
+ ///
+ /// <RichTextBlock Width="400">
+ /// <Paragraph>
+ /// <Run Text="{Binding Content}"/>
+ /// </Paragraph>
+ /// </RichTextBlock>
+ /// </RichTextColumns>
+ /// </code>
+ /// </example>
+ /// <remarks>Typically used in a horizontally scrolling region where an unbounded amount of
+ /// space allows for all needed columns to be created. When used in a vertically scrolling
+ /// space there will never be any additional columns.</remarks>
+ [Windows.UI.Xaml.Markup.ContentProperty(Name = "RichTextContent")]
+ public sealed class RichTextColumns : Panel
+ {
+ /// <summary>
+ /// Identifies the <see cref="RichTextContent"/> dependency property.
+ /// </summary>
+ public static readonly DependencyProperty RichTextContentProperty =
+ DependencyProperty.Register("RichTextContent", typeof(RichTextBlock),
+ typeof(RichTextColumns), new PropertyMetadata(null, ResetOverflowLayout));
+
+ /// <summary>
+ /// Identifies the <see cref="ColumnTemplate"/> dependency property.
+ /// </summary>
+ public static readonly DependencyProperty ColumnTemplateProperty =
+ DependencyProperty.Register("ColumnTemplate", typeof(DataTemplate),
+ typeof(RichTextColumns), new PropertyMetadata(null, ResetOverflowLayout));
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="RichTextColumns"/> class.
+ /// </summary>
+ public RichTextColumns()
+ {
+ this.HorizontalAlignment = HorizontalAlignment.Left;
+ }
+
+ /// <summary>
+ /// Gets or sets the initial rich text content to be used as the first column.
+ /// </summary>
+ public RichTextBlock RichTextContent
+ {
+ get { return (RichTextBlock)GetValue(RichTextContentProperty); }
+ set { SetValue(RichTextContentProperty, value); }
+ }
+
+ /// <summary>
+ /// Gets or sets the template used to create additional
+ /// <see cref="RichTextBlockOverflow"/> instances.
+ /// </summary>
+ public DataTemplate ColumnTemplate
+ {
+ get { return (DataTemplate)GetValue(ColumnTemplateProperty); }
+ set { SetValue(ColumnTemplateProperty, value); }
+ }
+
+ /// <summary>
+ /// Invoked when the content or overflow template is changed to recreate the column layout.
+ /// </summary>
+ /// <param name="d">Instance of <see cref="RichTextColumns"/> where the change
+ /// occurred.</param>
+ /// <param name="e">Event data describing the specific change.</param>
+ private static void ResetOverflowLayout(DependencyObject d, DependencyPropertyChangedEventArgs e)
+ {
+ // When dramatic changes occur, rebuild the column layout from scratch
+ var target = d as RichTextColumns;
+ if (target != null)
+ {
+ target._overflowColumns = null;
+ target.Children.Clear();
+ target.InvalidateMeasure();
+ }
+ }
+
+ /// <summary>
+ /// Lists overflow columns already created. Must maintain a 1:1 relationship with
+ /// instances in the <see cref="Chidren"/> collection following the initial RichTextBlock
+ /// child.
+ /// </summary>
+ private List<RichTextBlockOverflow> _overflowColumns = null;
+
+ /// <summary>
+ /// Determines whether additional overflow columns are needed and if existing columns can
+ /// be removed.
+ /// </summary>
+ /// <param name="availableSize">The size of the space available, used to constrain the
+ /// number of additional columns that can be created.</param>
+ /// <returns>The resulting size of the original content plus any extra columns.</returns>
+ protected override Size MeasureOverride(Size availableSize)
+ {
+ if (this.RichTextContent == null) return new Size(0, 0);
+
+ // Make sure the RichTextBlock is a child, using the lack of
+ // a list of additional columns as a sign that this hasn't been
+ // done yet
+ if (this._overflowColumns == null)
+ {
+ Children.Add(this.RichTextContent);
+ this._overflowColumns = new List<RichTextBlockOverflow>();
+ }
+
+ // Start by measuring the original RichTextBlock content
+ this.RichTextContent.Measure(availableSize);
+ var maxWidth = this.RichTextContent.DesiredSize.Width;
+ var maxHeight = this.RichTextContent.DesiredSize.Height;
+ var hasOverflow = this.RichTextContent.HasOverflowContent;
+
+ // Make sure there are enough overflow columns
+ int overflowIndex = 0;
+ while (hasOverflow && maxWidth < availableSize.Width && this.ColumnTemplate != null)
+ {
+ // Use existing overflow columns until we run out, then create
+ // more from the supplied template
+ RichTextBlockOverflow overflow;
+ if (this._overflowColumns.Count > overflowIndex)
+ {
+ overflow = this._overflowColumns[overflowIndex];
+ }
+ else
+ {
+ overflow = (RichTextBlockOverflow)this.ColumnTemplate.LoadContent();
+ this._overflowColumns.Add(overflow);
+ this.Children.Add(overflow);
+ if (overflowIndex == 0)
+ {
+ this.RichTextContent.OverflowContentTarget = overflow;
+ }
+ else
+ {
+ this._overflowColumns[overflowIndex - 1].OverflowContentTarget = overflow;
+ }
+ }
+
+ // Measure the new column and prepare to repeat as necessary
+ overflow.Measure(new Size(availableSize.Width - maxWidth, availableSize.Height));
+ maxWidth += overflow.DesiredSize.Width;
+ maxHeight = Math.Max(maxHeight, overflow.DesiredSize.Height);
+ hasOverflow = overflow.HasOverflowContent;
+ overflowIndex++;
+ }
+
+ // Disconnect extra columns from the overflow chain, remove them from our private list
+ // of columns, and remove them as children
+ if (this._overflowColumns.Count > overflowIndex)
+ {
+ if (overflowIndex == 0)
+ {
+ this.RichTextContent.OverflowContentTarget = null;
+ }
+ else
+ {
+ this._overflowColumns[overflowIndex - 1].OverflowContentTarget = null;
+ }
+ while (this._overflowColumns.Count > overflowIndex)
+ {
+ this._overflowColumns.RemoveAt(overflowIndex);
+ this.Children.RemoveAt(overflowIndex + 1);
+ }
+ }
+
+ // Report final determined size
+ return new Size(maxWidth, maxHeight);
+ }
+
+ /// <summary>
+ /// Arranges the original content and all extra columns.
+ /// </summary>
+ /// <param name="finalSize">Defines the size of the area the children must be arranged
+ /// within.</param>
+ /// <returns>The size of the area the children actually required.</returns>
+ protected override Size ArrangeOverride(Size finalSize)
+ {
+ double maxWidth = 0;
+ double maxHeight = 0;
+ foreach (var child in Children)
+ {
+ child.Arrange(new Rect(maxWidth, 0, child.DesiredSize.Width, finalSize.Height));
+ maxWidth += child.DesiredSize.Width;
+ maxHeight = Math.Max(maxHeight, child.DesiredSize.Height);
+ }
+ return new Size(maxWidth, maxHeight);
+ }
+ }
+}
View
943 WinRT-MVVM-Example/Common/StandardStyles.xaml
@@ -0,0 +1,943 @@
+<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 ApplicationTextBrush}"/>
+ <Setter Property="FontSize" Value="{StaticResource ContentFontSize}"/>
+ <Setter Property="FontFamily" Value="{StaticResource ContentFontFamily}"/>
+ <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 ApplicationTextBrush}"/>
+ <Setter Property="FontSize" Value="{StaticResource ContentFontSize}"/>
+ <Setter Property="FontFamily" Value="{StaticResource ContentFontFamily}"/>
+ <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 ApplicationSecondaryTextBrush}"/>
+ </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 FocusVisualWhiteStrokeBrush}"
+ StrokeEndLineCap="Square"
+ StrokeDashArray="1,1"
+ Opacity="0"
+ StrokeDashOffset="1.5"/>
+ <Rectangle
+ x:Name="FocusVisualBlack"
+ IsHitTestVisible="False"
+ Stroke="{StaticResource FocusVisualBlackStrokeBrush}"
+ 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 ApplicationHoverTextBrush}"/>
+ </ObjectAnimationUsingKeyFrames>
+ </Storyboard>
+ </VisualState>
+ <VisualState x:Name="Pressed">
+ <Storyboard>
+ <ObjectAnimationUsingKeyFrames Storyboard.TargetName="Text" Storyboard.TargetProperty="Foreground">
+ <DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource ApplicationPressedTextBrush}"/>
+ </ObjectAnimationUsingKeyFrames>
+ </Storyboard>
+ </VisualState>
+ <VisualState x:Name="Disabled">
+ <Storyboard>
+ <ObjectAnimationUsingKeyFrames Storyboard.TargetName="Text" Storyboard.TargetProperty="Foreground">
+ <DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource ControlDisabledTextBrush}"/>
+ </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 FocusVisualWhiteStrokeBrush}"
+ StrokeEndLineCap="Square"
+ StrokeDashArray="1,1"
+ Opacity="0"
+ StrokeDashOffset="1.5"/>
+ <Rectangle
+ x:Name="FocusVisualBlack"
+ IsHitTestVisible="False"
+ Stroke="{StaticResource FocusVisualBlackStrokeBrush}"
+ 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 ApplicationHoverTextBrush}"/>
+ </ObjectAnimationUsingKeyFrames>
+ </Storyboard>
+ </VisualState>
+ <VisualState x:Name="Pressed">
+ <Storyboard>
+ <ObjectAnimationUsingKeyFrames Storyboard.TargetName="Text" Storyboard.TargetProperty="Foreground">
+ <DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource ApplicationPressedTextBrush}"/>
+ </ObjectAnimationUsingKeyFrames>
+ </Storyboard>
+ </VisualState>
+ <VisualState x:Name="Disabled">
+ <Storyboard>
+ <ObjectAnimationUsingKeyFrames Storyboard.TargetName="Text" Storyboard.TargetProperty="Foreground">
+ <DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource ControlDisabledTextBrush}"/>
+ </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 ApplicationSecondaryTextBrush}"/>
+ </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 AppBarItemForegroundBrush}"/>
+ <Setter Property="VerticalAlignment" Value="Stretch"/>
+ <Setter Property="FontFamily" Value="Segoe UI Symbol"/>
+ <Setter Property="FontWeight" Value="Normal"/>
+ <Setter Property="FontSize" Value="21.333"/>
+ <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 AppBarItemBackgroundBrush}"/>
+ <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 FocusVisualWhiteStrokeBrush}"
+ StrokeEndLineCap="Square"
+ StrokeDashArray="1,1"
+ Opacity="0"
+ StrokeDashOffset="1.5"/>
+ <Rectangle
+ x:Name="FocusVisualBlack"
+ IsHitTestVisible="False"
+ Stroke="{StaticResource FocusVisualBlackStrokeBrush}"
+ 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 AppBarItemHoverBackgroundBrush}"/>
+ </ObjectAnimationUsingKeyFrames>
+ <ObjectAnimationUsingKeyFrames Storyboard.TargetName="Content" Storyboard.TargetProperty="Foreground">
+ <DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource AppBarItemHoverForegroundBrush}"/>
+ </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 AppBarItemForegroundBrush}"/>
+ </ObjectAnimationUsingKeyFrames>
+ <ObjectAnimationUsingKeyFrames Storyboard.TargetName="Content" Storyboard.TargetProperty="Foreground">
+ <DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource AppBarItemPressedForegroundBrush}"/>
+ </ObjectAnimationUsingKeyFrames>
+ </Storyboard>
+ </VisualState>
+ <VisualState x:Name="Disabled">
+ <Storyboard>
+ <ObjectAnimationUsingKeyFrames Storyboard.TargetName="OutlineGlyph" Storyboard.TargetProperty="Foreground">
+ <DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource AppBarItemDisabledForegroundBrush}"/>
+ </ObjectAnimationUsingKeyFrames>
+ <ObjectAnimationUsingKeyFrames Storyboard.TargetName="Content" Storyboard.TargetProperty="Foreground">
+ <DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource AppBarItemDisabledForegroundBrush}"/>
+ </ObjectAnimationUsingKeyFrames>
+ <ObjectAnimationUsingKeyFrames Storyboard.TargetName="TextLabel" Storyboard.TargetProperty="Foreground">
+ <DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource AppBarItemDisabledForegroundBrush}"/>
+ </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>
+
+ <!-- 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 BackButtonBackgroundBrush}"/>
+ <TextBlock x:Name="NormalGlyph" Text="{StaticResource BackButtonGlyph}" Foreground="{StaticResource BackButtonGlyphBrush}"/>
+ <TextBlock x:Name="ArrowGlyph" Text="&#xE0A6;" Foreground="{StaticResource BackButtonPressedGlyphBrush}" Opacity="0"/>
+ </Grid>
+ <Rectangle
+ x:Name="FocusVisualWhite"
+ IsHitTestVisible="False"
+ Stroke="{StaticResource FocusVisualWhiteStrokeBrush}"
+ StrokeEndLineCap="Square"
+ StrokeDashArray="1,1"
+ Opacity="0"
+ StrokeDashOffset="1.5"/>
+ <Rectangle
+ x:Name="FocusVisualBlack"
+ IsHitTestVisible="False"
+ Stroke="{StaticResource FocusVisualBlackStrokeBrush}"
+ 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 BackButtonHoverBackgroundBrush}"/>
+ </ObjectAnimationUsingKeyFrames>
+ <ObjectAnimationUsingKeyFrames Storyboard.TargetName="NormalGlyph" Storyboard.TargetProperty="Foreground">
+ <DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource BackButtonHoverGlyphBrush}"/>
+ </ObjectAnimationUsingKeyFrames>
+ </Storyboard>
+ </VisualState>
+ <VisualState x:Name="Pressed">
+ <Storyboard>
+ <ObjectAnimationUsingKeyFrames Storyboard.TargetName="BackgroundGlyph" Storyboard.TargetProperty="Foreground">
+ <DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource BackButtonGlyphBrush}"/>
+ </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 BackButtonBackgroundBrush}"/>
+ <TextBlock x:Name="NormalGlyph" Text="{StaticResource BackButtonSnappedGlyph}" Foreground="{StaticResource BackButtonGlyphBrush}"/>
+ <TextBlock x:Name="ArrowGlyph" Text="&#xE0C4;" Foreground="{StaticResource BackButtonPressedGlyphBrush}" Opacity="0"/>
+ </Grid>
+ <Rectangle
+ x:Name="FocusVisualWhite"
+ IsHitTestVisible="False"
+ Stroke="{StaticResource FocusVisualWhiteStrokeBrush}"
+ StrokeEndLineCap="Square"
+ StrokeDashArray="1,1"
+ Opacity="0"
+ StrokeDashOffset="1.5"/>
+ <Rectangle
+ x:Name="FocusVisualBlack"
+ IsHitTestVisible="False"
+ Stroke="{StaticResource FocusVisualBlackStrokeBrush}"
+ 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 BackButtonHoverBackgroundBrush}"/>
+ </ObjectAnimationUsingKeyFrames>
+ <ObjectAnimationUsingKeyFrames Storyboard.TargetName="NormalGlyph" Storyboard.TargetProperty="Foreground">
+ <DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource BackButtonHoverGlyphBrush}"/>
+ </ObjectAnimationUsingKeyFrames>
+ </Storyboard>
+ </VisualState>
+ <VisualState x:Name="Pressed">
+ <Storyboard>
+ <ObjectAnimationUsingKeyFrames Storyboard.TargetName="BackgroundGlyph" Storyboard.TargetProperty="Foreground">
+ <DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource BackButtonGlyphBrush}"/>
+ </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 ListViewItemPlaceholderRectBrush}">
+ <Image Source="{Binding Image}" Stretch="UniformToFill"/>
+ </Border>
+ <StackPanel VerticalAlignment="Bottom" Background="{StaticResource ListViewItemOverlayBackgroundBrush}">
+ <TextBlock Text="{Binding Title}" Foreground="{StaticResource ListViewItemOverlayTextBrush}" Style="{StaticResource TitleTextStyle}" Height="60" Margin="15,0,15,0"/>
+ <TextBlock Text="{Binding Subtitle}" Foreground="{StaticResource ListViewItemOverlaySecondaryTextBrush}" 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 ListViewItemPlaceholderRectBrush}" 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 ListViewItemPlaceholderRectBrush}" 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 ListViewItemPlaceholderRectBrush}" 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 ListViewItemPlaceholderRectBrush}" 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 ApplicationSecondaryTextBrush}" 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 ListViewItemPlaceholderRectBrush}" 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 ApplicationSecondaryTextBrush}" 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 ListViewItemPlaceholderRectBrush}">
+ <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 ApplicationPageBackgroundBrush}">
+ <Grid.ColumnDefinitions>
+ <ColumnDefinition Width="Auto"/>
+ <ColumnDefinition Width="*"/>
+ </Grid.ColumnDefinitions>
+
+ <Grid Background="{StaticResource ListViewItemPlaceholderRectBrush}" 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 ApplicationSecondaryTextBrush}" 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>
+</ResourceDictionary>
View
53 WinRT-MVVM-Example/Infrastructure/DelegateCommand.cs
@@ -0,0 +1,53 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows.Input;
+
+namespace Application6
+{
+ public class DelegateCommand : ICommand
+ {
+ private readonly Func<object, bool> canExecute;
+ private readonly Action<object> executeAction;
+ bool canExecuteCache;
+
+ public DelegateCommand(Action<object> executeAction, Func<object, bool> canExecute)
+ {
+ this.executeAction = executeAction;
+ this.canExecute = canExecute;
+ }
+
+ public bool CanExecute(object parameter)
+ {
+ bool temp = canExecute(parameter);
+
+ if (canExecuteCache != temp)
+ {
+ canExecuteCache = temp;
+ if (CanExecuteChanged != null)
+ {
+ CanExecuteChanged(this, new EventArgs());
+ }
+ }
+
+ return canExecuteCache;
+ }
+
+ public event EventHandler CanExecuteChanged;
+
+ public void RaiseExecuteChanged()
+ {
+ if (CanExecuteChanged == null)
+ return;
+
+ CanExecuteChanged(this, null);
+ }
+
+ public void Execute(object parameter)
+ {
+ executeAction(parameter);
+ }
+ }
+}
View
42 WinRT-MVVM-Example/Infrastructure/NavigationService.cs
@@ -0,0 +1,42 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Windows.UI.Xaml.Controls;
+
+namespace Application6
+{
+ public class NavigationService
+ {
+ readonly Frame frame;
+
+ public NavigationService(Frame frame)
+ {
+ this.frame = frame;
+ }
+
+ public void GoBack()
+ {
+ frame.GoBack();
+ }
+
+ public void GoForward()
+ {
+ frame.GoForward();
+ }
+
+ public bool Navigate<T>(object parameter = null)
+ {
+ var type = typeof(T);
+
+ return Navigate(type, parameter);
+ }
+
+ public bool Navigate(Type source, object parameter = null)
+ {
+ return frame.Navigate(source, parameter);
+ }
+ }
+
+}
View
27 WinRT-MVVM-Example/Infrastructure/ViewModelLocator.cs
@@ -0,0 +1,27 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Application6
+{
+ public class ViewModelLocator
+ {
+ public BlankPageViewModel BlankPageViewModel
+ {
+ get
+ {
+ return new BlankPageViewModel(App.NavigationService);
+ }
+ }
+
+ public SecondPageViewModel SecondPageViewModel
+ {
+ get
+ {
+ return new SecondPageViewModel(App.NavigationService);
+ }
+ }
+ }
+}
View
43 WinRT-MVVM-Example/Package.appxmanifest
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Package xmlns="http://schemas.microsoft.com/appx/2010/manifest">
+
+ <Identity Name="b6564030-cb57-424a-aeba-159b6199aaa9"
+ Publisher="CN=Mikael"
+ Version="1.0.0.0" />
+
+ <Properties>
+ <DisplayName>Application6</DisplayName>
+ <PublisherDisplayName>Mikael</PublisherDisplayName>
+ <Logo>Assets\StoreLogo.png</Logo>
+ <Description>Application6</Description>
+ </Properties>
+
+ <Prerequisites>
+ <OSMinVersion>6.2</OSMinVersion>
+ <OSMaxVersionTested>6.2</OSMaxVersionTested>
+ </Prerequisites>
+
+ <Resources>
+ <Resource Language="x-generate"/>
+ </Resources>
+
+ <Applications>
+ <Application Id="App"
+ Executable="$targetnametoken$.exe"
+ EntryPoint="Application6.App">
+ <VisualElements
+ DisplayName="Application6"
+ Logo="Assets\Logo.png"
+ SmallLogo="Assets\SmallLogo.png"
+ Description="Application6"
+ ForegroundText="light"
+ BackgroundColor="#222222">
+ <DefaultTile ShowName="allLogos" />
+ <SplashScreen Image="Assets\SplashScreen.png" />
+ </VisualElements>
+ </Application>
+ </Applications>
+ <Capabilities>
+ <Capability Name="internetClient" />
+ </Capabilities>
+</Package>
View
29 WinRT-MVVM-Example/Properties/AssemblyInfo.cs
@@ -0,0 +1,29 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("Application6")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("Microsoft")]
+[assembly: AssemblyProduct("Application6")]
+[assembly: AssemblyCopyright("Copyright © Microsoft 2012")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Version information for an assembly consists of the following four values:
+//
+// Major Version
+// Minor Version
+// Build Number
+// Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers
+// by using the '*' as shown below:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
+[assembly: ComVisible(false)]
View
15 WinRT-MVVM-Example/SecondPage.xaml
@@ -0,0 +1,15 @@
+<Page
+ x:Class="Application6.SecondPage"
+ xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
+ xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+ xmlns:local="using:Application6"
+ xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
+ xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
+ DataContext="{Binding SecondPageViewModel, Source={StaticResource ViewModelLocator}}"
+ mc:Ignorable="d">
+