Windows 8.1 – Screen Mode Detection

During the development of my Windows Store application I faced out that is not that easy to detect the current screen mode to adjust consequently the layout.

These are the different screen modes available in Windows 8:

  • Portait orientation.
  • Landscape orientation, Full Screen.
  • Landscape orientation, Snapped. Sharing the screen with other applications, see the next image as an example.

Windows 8 - Screen Sharing

When the application is sharing the screen with other applications it is also important to distinguish between having a big portion of the screen or not:

smallPortionScreen

In Windows 8 it was easier to detect the screen mode:

private void WindowSizeChanged(object sender, WindowSizeChangedEventArgs e) {
    // Get view state
    ApplicationViewState currentViewState = ApplicationView.Value;

    if (currentViewState == ApplicationViewState.FullScreenLandscape) {
       // Full screen Landscape layout
    }
    else if (currentViewState == ApplicationViewState.FullScreenPortrait) {
       // Full screen Portrait layout
    }
    else if (currentViewState == ApplicationViewState.Filled) {
       // Filled layout
    }
    else if (currentViewState == ApplicationViewState.Snapped) {
       // Snapped layout
    }
}

But in Windows 8.1 the ApplicationView is deprecated, developers can only know if the screen is in Landscape or Portrait. I implemented a helper class called ScreenManager to get the current screen mode, this class has also an Event to notify when the screen mode changed:

These are the Screen Modes that I defined: Continue reading

Windows 8.1 – Data Persistance

Windows Store applications can persist runtime state, user preferences, and other settings using different mechanisms:

  • Local: Persistent data that exists only on the current device.
  • Roaming: Data that exists on all devices on which the user has installed the app.
  • Temporary: Data that could be removed by the system at any time.
var localSettings = ApplicationData.Current.LocalSettings;
var roamingSettings = ApplicationData.Current.RoamingSettings;
var tempFolder = ApplicationData.Current.TemporaryFolder;

In this post I will share my helper class to store objects using the LocalSettings container.

One problem I found when I tried to save an object to the LocalSettings is that it only supports the following types:

UInt8, Int16, UInt16, Int32, UInt32, Int64, UInt64, Single, Double
Boolean
Char16, String
DateTime, TimeSpan
GUID, Point, Size, Rect
ApplicationDataCompositeValue

For the application that I am working on I needed to store an instance of my settings data class, this class was already prepared for serialization. After playing around a little bit I found an easy solution implementing a helper class that serializes my object to XML and saves it as string.

StorageManager.cs

using Windows.Storage;

namespace WindowsStore.Common.Storage
{
    public class StorageManager
    {
        /// <summary>
        /// Initializes a new instance of the  <see cref="StorageManager" /> class.
        /// As the LocalSettings is divided in containers the constructor needs the key of the container to use.
        /// </summary>
        /// <param name="containerKey">The key.</param>
        /// <param name="isRoaming">if set to <c>true</c> [is roaming].</param>
        public StorageManager(string containerKey, bool isRoaming)
        {
            if (isRoaming)
            {
                InitializeRoamingAppContainer(containerKey);
            }
            else
            {
                InitializeLocalAppContainer(containerKey);
            }
        }

        /// <summary>
        /// Determines whether the local storage contains an object associated to the specified key.
        /// </summary>
        public bool Contains(string key)
        {
            return AppSettingsContainer.Values.ContainsKey(key);
        }

        /// <summary>
        /// Saves the specified object associated to the specified key.
        /// </summary>
        public void Save(string key, object value)
        {
            var serializedValue = XMLSerializer.SerializeToString(value);

            if (AppSettingsContainer.Values.ContainsKey(key))
            {
                AppSettingsContainer.Values[key] = serializedValue;
            }
            else
            {
                AppSettingsContainer.Values.Add(key, serializedValue);
            }
        }

        /// <summary>
        /// Loads an object associated to the specified key.
        /// </summary>
        public T Load<T>(string key)
        {
            if (AppSettingsContainer.Values.ContainsKey(key))
            {
                return XMLSerializer.DeserializeFromString<T>(AppSettingsContainer.Values[key].ToString());
            }

            return default(T);
        }

        /// <summary>
        /// Removes the object associated to the specified key.
        /// </summary>
        public bool Remove(string key)
        {
            if (AppSettingsContainer.Values.ContainsKey(key))
            {
                return AppSettingsContainer.Values.Remove(key);
            }
            return false;
        }

        #region privates

        /// <summary>
        /// Initializes a roaming application container.
        /// </summary>
        /// <param name="containerKey">The container key.</param>
        private void InitializeRoamingAppContainer(string containerKey)
        {
            // todo RoamingQuota
            if (!ApplicationData.Current.RoamingSettings.Containers.ContainsKey(containerKey))
            {
                ApplicationData.Current.RoamingSettings.CreateContainer(containerKey,
                    ApplicationDataCreateDisposition.Always);
            }

            this.AppSettingsContainer = ApplicationData.Current.RoamingSettings.Containers[containerKey];
        }

        /// <summary>
        /// Initializes a local application container.
        /// </summary>
        /// <param name="containerKey">The container key.</param>
        private void InitializeLocalAppContainer(string containerKey)
        {
            if (!ApplicationData.Current.LocalSettings.Containers.ContainsKey(containerKey))
            {
                ApplicationData.Current.LocalSettings.CreateContainer(containerKey,
                    ApplicationDataCreateDisposition.Always);
            }

            this.AppSettingsContainer = ApplicationData.Current.LocalSettings.Containers[containerKey];
        }

        /// <summary>
        /// Gets or sets the application settings container.
        /// </summary>
        private ApplicationDataContainer AppSettingsContainer { get; set; }

        #endregion

    }
}

XMLSerializer.cs

using System.IO;
using System.Xml.Serialization;

namespace WindowsStore.Common.Storage
{
    public static class XMLSerializer
    {
        /// <summary>
        /// Serializes an object to string using XML.
        /// </summary>
        /// <param name="obj">The object.</param>
        public static string SerializeToString(object obj)
        {
            XmlSerializer serializer = new XmlSerializer(obj.GetType());
            using (StringWriter writer = new StringWriter())
            {
                serializer.Serialize(writer, obj);
                return writer.ToString();
            }
        }

        /// <summary>
        /// De-serializes an object from XML string.
        /// </summary>
        /// <typeparam name="T">Type of the object to deserialize</typeparam>
        /// <param name="xml">The XML.</param>
        public static T DeserializeFromString<T>(string xml)
        {
            XmlSerializer deserializer = new XmlSerializer(typeof(T));
            using (StringReader reader = new StringReader(xml))
            {
                return (T)deserializer.Deserialize(reader);
            }
        }
    }
}

References: