Showing posts with label Windows RT. Show all posts
Showing posts with label Windows RT. Show all posts

Monday, September 9, 2013

Value Converter to Binding in Windows Store Apps Using XAML


Introduction of IValueConverter Interface.

IValueConverter is an interface that is use to create a custom converter class by deriving from this interface. Basically IValueConverter has two methods:

  1. Convert: This method is used to create a One-way data binding to a UI element by converting its value. If you implement one-way binding to a target element, then you have to use the Convert Method. In other words when data is passed from the source, the binding engine calls Convert.
  2. ConvertBack: This method is used when you bind the data to a target element using Two-way binding. In the other words you can say that when data is passed from the target, the binding engine calls ConvertBack and passes the returned data to the source.
Once a value converter is created, you can select the value converter in the XAML Designer when you configure a data binding.

Let's see an example to understand it better.

Follow these steps..

Step 1

Create a blank Windows Store apps application using XAML and C#.

Step 2

In this example we use two textboxes and convert the value based on the first textbox, then show the converted value into the second texbox.

Here is the code of XAML.

<StackPanel Margin="5">
   <TextBlock Style="{StaticResource BasicTextStyle}" Text="Percent grade:" Margin="5" />
   <TextBox x:Name="ValueConverter" Text="70" Margin="5"/>
   <TextBlock Style="{StaticResource BasicTextStyle}" Text="Letter grade:" Margin="5"/>
   <TextBox x:Name="tbValueConverterDataBound"
Margin="5" Width="150"/>
</StackPanel>

Step 3

To create a Custom Converter I will create a converter class that implements the IValueConverter Interface and implements the Convert method in this class. This method takes four types of arguements but we only require the first paremeter that contrains the value to be converted and returned back.

To add a .cs file:

Add-Class-In-Windows-Store-Apps.jpg

Add-NewClass-File-In-Windows-Store-Apps.jpg

Here is the code of the .cs file:
 
public class ValueConverter : IValueConverter
{
        //Convert the textbox value into Grades
    public object Convert(object value, System.Type type, object parameter, string language)
    {
        int _value;
        string _grade = string.Empty;
       //try parsing the value to int
       if (Int32.TryParse(value.ToString(), out _value))
       {
                if (_value < 50)
                    _grade = "F";
                else if (_value < 60)
                    _grade = "D";
                else if (_value < 70)
                    _grade = "C";
                else if (_value < 80)
                    _grade = "B";
                else if (_value < 90)
                    _grade = "A";
                else if (_value < 100)
                    _grade = "A+";
                else if (_value == 100)
                    _grade = "SUPER STAR!";
        }
            return _grade;
     }
    public object ConvertBack(object value, System.Type type, object parameter, string language)
   {
        throw new NotImplementedException(); //doing one-way binding so this is not required.
   }
}

Step 4

Now, in the XAML file I will create a static resource of the converter class and give the key to this resource, so we can use it later for conversion.
<StackPanel.Resources>
    <local:ValueConverter x:Key="GradeConverter"/>                         
</StackPanel.Resources>
Step 5

In this step I will give the static resource that I defined perviously to the result textbox by binding its text property.
<TextBox x:Name="tbValueConverterDataBound" Text="{Binding ElementName=ValueConverter,
       
 Path=Text, Mode=OneWay, Converter={StaticResource GradeConverter}}" Margin="5" Width="150"/>

Here is the full code:
 
<Grid x:Name="Output" HorizontalAlignment="Left" VerticalAlignment="Top" Grid.Row="1">
   <StackPanel Margin="5">
    <!-- Add converter as a resource to reference it from a Binding. -->
      <StackPanel.Resources>
         <local:S2Formatter x:Key="GradeConverter"/>                         
      </StackPanel.Resources>
      <TextBlock Style="{StaticResource BasicTextStyle}" Text="Percent grade:" Margin="5" />
      <TextBox x:Name="ValueConverter" Text="70" Margin="5"/>
      <TextBlock Style="{StaticResource BasicTextStyle}" Text="Letter grade:" Margin="5"/>
      <TextBox x:Name="tbValueConverterDataBound" Text="{Binding ElementName=ValueConverter,
             
 Path=Text, Mode=OneWay, Converter={StaticResource GradeConverter}}" Margin="5" Width="150"/>
   </StackPanel>
</Grid>
Step 6

Now, build the application and run it.

You will see that the value of the second textbox is converted from the value in the first textbox; look at:


If you change the value of first textbox, then the converted value will be reflected in the second textbox since I used one way binding.

IValueConverter-Interface-In-Windows-Store-Apps.jpg

Friday, August 2, 2013

Modal Popup & Flyout Popup in WinRT




First I created a child window base class:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Windows.UI;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Controls.Primitives;
using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Media.Animation;

namespace PopupSample.Bases
{
    public class ChildWindowBase : UserControl, IDisposable
    {
        public ChildWindowBase() : base()
        {

        }

        public Page Opener { get; set; }
        public bool? DialogResult { get; set; }

        public string ChildWindowName
        {
            get { return this.GetType().Name; }
        }

        private static Popup _popup;
        private static Popup _RootPopup;

        [DefaultValue(FlyoutType.Center)]
        public FlyoutType Flyout { get; set; }

        public void Show()
        {
            switch (Flyout)
            {
                //Modal Popup
                case FlyoutType.Center:
                    CenterShow();
                    break;
                case FlyoutType.Left:
                    LeftShow();
                    break;
                case FlyoutType.Top:
                    TopShow();
                    break;
                case FlyoutType.Right:
                    RightShow();
                    break;
                case FlyoutType.Bottom:
                    BottomShow();
                    break;
                default:
                    break;
            }
        }

        private void CenterShow()
        {
            var bounds = Window.Current.Bounds;
            var width = Double.IsNaN(this.Width) ? 900 : this.Width;
            var height = Double.IsNaN(this.Height) ? 550 : this.Height;

            Grid RootPanel = new Grid
            {
                Name = "RootPanel",
                Opacity = 0.60,
                Background = new SolidColorBrush(Colors.White),
                Width = bounds.Width,
                Height = bounds.Height,
                VerticalAlignment = Windows.UI.Xaml.VerticalAlignment.Stretch,
                HorizontalAlignment = Windows.UI.Xaml.HorizontalAlignment.Stretch
            };

            _RootPopup = new Popup
            {
                Child = RootPanel
            };

            _popup = new Popup
            {
                ChildTransitions = new TransitionCollection
                                                    {
                                                        new AddDeleteThemeTransition(),
                                                        new PopupThemeTransition {FromVerticalOffset = bounds.Height}
                                                    },
                HorizontalOffset = (bounds.Width / 2) - (width / 2),
                VerticalOffset = (bounds.Height / 2) - (height / 2),
                Child = this,
            };

            _RootPopup.IsOpen = true;
            (Window.Current.Content as Frame).IsEnabled = false;
            _popup.IsOpen = true;

            OnShowCompleted(EventArgs.Empty);
        }

        private void LeftShow()
        {
            var bounds = Window.Current.Bounds;

            var width = Double.IsNaN(this.Width) ? 480 : this.Width;
            (this.Content as FrameworkElement).Height = bounds.Height;

            _popup = new Popup
            {
                ChildTransitions = new TransitionCollection
                                                    {
                                                        new EntranceThemeTransition {FromHorizontalOffset = 0},
                                                    },
                HorizontalOffset = 0,
                IsLightDismissEnabled = true,
                Child = this,
            };

            _popup.IsOpen = true;

            OnShowCompleted(EventArgs.Empty);
        }

        private void TopShow()
        {
            var bounds = Window.Current.Bounds;

            var height = Double.IsNaN(this.Height) ? 200 : this.Height;
            (this.Content as FrameworkElement).Width = bounds.Width;

            _popup = new Popup
            {
                ChildTransitions = new TransitionCollection
                                                    {
                                                        new EntranceThemeTransition {FromVerticalOffset = 0}
                                                    },
                VerticalOffset = 0,
                IsLightDismissEnabled = true,
                Child = this,
            };

            _popup.IsOpen = true;

            OnShowCompleted(EventArgs.Empty);
        }

        private void RightShow()
        {
            var bounds = Window.Current.Bounds;

            var width = Double.IsNaN(this.Width) ? 480 : this.Width;
            (this.Content as FrameworkElement).Height = bounds.Height;

            _popup = new Popup
            {
                ChildTransitions = new TransitionCollection
                                                    {
                                                        new EntranceThemeTransition {FromHorizontalOffset = bounds.Width}
                                                    },
                HorizontalOffset = bounds.Width - width,
                IsLightDismissEnabled = true,
                Child = this,
            };

            _popup.IsOpen = true;

            OnShowCompleted(EventArgs.Empty);
        }

        private void BottomShow()
        {
            var bounds = Window.Current.Bounds;

            var height = Double.IsNaN(this.Height) ? 200 : this.Height;
            (this.Content as FrameworkElement).Width = bounds.Width;

            _popup = new Popup
            {
                ChildTransitions = new TransitionCollection
                                                    {
                                                        new EntranceThemeTransition {FromVerticalOffset = bounds.Height}
                                                    },
                VerticalOffset = bounds.Height - height,
                IsLightDismissEnabled = true,
                Child = this,
            };

            _popup.IsOpen = true;

            OnShowCompleted(EventArgs.Empty);
        }

        public void Close()
        {
            _popup.IsOpen = false;
            (Window.Current.Content as Frame).IsEnabled = true;

            if (Flyout == FlyoutType.Center)
            {
                _RootPopup.IsOpen = false;
            }

            OnClosed(EventArgs.Empty);
        }

        public void OnInitialized()
        {

        }

        public event EventHandler Closed;
        public event EventHandler ShowCompleted;

        protected virtual void OnClosed(EventArgs e)
        {
            if (Closed != null)
                Closed(this, e);
        }

        protected virtual void OnShowCompleted(EventArgs e)
        {
            if (ShowCompleted != null)
                ShowCompleted(this, e);
        }

        #region IDisposable Members

        public virtual async void Dispose()
        {
            try
            {
                await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () =>
                {
                    this.Close();
                    this.Content = null;
                });
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }


        #endregion
    }

    public enum FlyoutType
    {
        Center,
        Left,
        Top,
        Right,
        Bottom
    }
}
 

For selecting popup type (modal or flyout) I use an enum (FlyoutType) if FlyoutType = Center then the popup is modal else the popup is flyout.


Modal Sample:
XAML:

<bases:ChildWindowBase
    x:Class="PopupSample.ChildWindows.ModalSample"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:bases="using:PopupSample.Bases"
    mc:Ignorable="d"
    d:DesignHeight="216"
    d:DesignWidth="384"
    Height="216"
    Width="384">

    <Border BorderThickness="2" BorderBrush="#FF8F8B8B" Background="DarkOrchid" CornerRadius="20">
        <Grid Margin="10">
            <Grid>
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="*" />
                </Grid.ColumnDefinitions>
                <Grid.RowDefinitions>
                    <RowDefinition Height="*" />
                    <RowDefinition Height="50"/>
                </Grid.RowDefinitions>

                <StackPanel Orientation="Horizontal" Grid.Row="1" HorizontalAlignment="Center">
                    <Button Width="100" Height="35" Content="Save" Click="btnSave_Click"/>
                    <Button Width="100" Height="35" Content="Cancel" Click="btnCancel_Click"/>
                </StackPanel>
            </Grid>
        </Grid>
    </Border>
</bases:ChildWindowBase>


CS:

using PopupSample.Bases;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
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.Media.Imaging;
using Windows.UI.Xaml.Navigation;

namespace PopupSample.ChildWindows
{
    public sealed partial class ModalSample : ChildWindowBase
    {
        public ModalSample()
        {
            this.InitializeComponent();

            this.Loaded += ModalSample_Loaded;
        }

        private void ModalSample_Loaded(object sender, RoutedEventArgs e)
        {
            
        }

        private void btnCancel_Click(object sender, RoutedEventArgs e)
        {
            this.DialogResult = false;
            this.Close();
        }

        private void btnSave_Click(object sender, RoutedEventArgs e)
        {
            this.DialogResult = true;
            this.Close();
        }
    }
}

DialogResualt is for returning value into opener window.


Open a modal popup:


ModalSample modal;

private void Modal_Click(object sender, RoutedEventArgs e)
{
    modal = new ModalSample();
    modal.ShowCompleted += modal_ShowCompleted;
    modal.Closed += modal_Closed;

    modal.Show();
}

void modal_ShowCompleted(object sender, EventArgs e)
{
    lstEvents.Items.Add(String.Format("modal_ShowCompleted - {0}", DateTime.Now));
}

void modal_Closed(object sender, EventArgs e)
{
    lstEvents.Items.Add(String.Format("modal_Closed - {0} - Resualt: {1}", DateTime.Now, modal.DialogResult));
}


ShowCompleted Event fire when popup opened successfully.
Closed Event fire when popup closed successfully.



Flyout Sample:

XAML:


<bases:ChildWindowBase
    x:Class="PopupSample.ChildWindows.FlyoutSample"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:bases="using:PopupSample.Bases"
    mc:Ignorable="d"
    d:DesignHeight="500"
    d:DesignWidth="384"
    MinWidth="384"
    MinHeight="500"
    Width="384">

    <Border BorderThickness="2" BorderBrush="#FF8F8B8B" Background="#FFDCD6D6">
        
    </Border>
</bases:ChildWindowBase>


CS:

using PopupSample.Bases;
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.Media.Imaging;
using Windows.UI.Xaml.Navigation;

namespace PopupSample.ChildWindows
{
    public sealed partial class FlyoutSample : ChildWindowBase
    {
        public FlyoutSample()
        {
            this.InitializeComponent();

            this.Loaded += FlayoutSample_Loaded;
        }

        private void FlayoutSample_Loaded(object sender, RoutedEventArgs e)
        {
            
        }
    }
}


Open a flyout popup:

FlyoutSample flyout;
        
private void Flyout_Click(object sender, RoutedEventArgs e)
{
    flyout = new FlyoutSample { Flyout = Bases.FlyoutType.Right };
    flyout.ShowCompleted += flyout_ShowCompleted;

    flyout.Show();
}

void flyout_ShowCompleted(object sender, EventArgs e)
{
    lstEvents.Items.Add(String.Format("flyout_ShowCompleted - {0}", DateTime.Now));
}




Download full sample from here

Thursday, August 1, 2013

WinRT IsoStorage Sample




First we should create a Storage Helper:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Xml.Serialization;
using Windows.Storage;
using System.IO;
using Windows.Storage.Streams;
using System.Xml.Linq;
using IsoStorageSample.Helpers;

namespace IsoStorageSample.Helpers
{
    public enum StorageType { Local, Temporary, Roaming }

    public class IsoStorage<T>
    {
        protected ApplicationData appData = Windows.Storage.ApplicationData.Current;
        protected StorageFolder storageFolder;
        protected StorageType storageType;

        public StorageType StorageType
        {
            get { return storageType; }
            set
            {
                storageType = value;
                // set the storage folder
                switch (storageType)
                {
                    case StorageType.Local:
                        storageFolder = appData.LocalFolder;
                        break;
                    case StorageType.Temporary:
                        storageFolder = appData.TemporaryFolder;
                        break;
                    case StorageType.Roaming:
                        storageFolder = appData.RoamingFolder;
                        break;
                    default:
                        throw new Exception(String.Format("Unknown StorageType: {0}", storageType));
                }
            }
        }

        public IsoStorage() : this(StorageType.Local) { }
        public IsoStorage(StorageType type)
        {
            StorageType = type;
        }

        public async Task CopyAsync(StorageFolder folder, string fileName)
        {
            try
            {
                StorageFile storageFile = await folder.GetFileAsync(fileName);

                if (await GetFileIfExistsAsync(storageFile.Name) == null)
                {
                    await storageFile.CopyAsync(storageFolder);
                }
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        public async Task<XDocument> LoadXml(string fileName)
        {
            try
            {
                StorageFile xmlFile = await GetFileIfExistsAsync(fileName);

                if (xmlFile != null)
                {
                    return XDocument.Load(xmlFile.Path);
                }
                else
                {
                    return null;
                }
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        /// <summary>
        /// Delete a file asynchronously
        /// </summary>
        /// <param name="fileName"></param>
        public async void DeleteAsync(string fileName)
        {
            try
            {
                fileName = AppendExt(fileName);
                var file = await GetFileIfExistsAsync(fileName);
                if (file != null)
                    await file.DeleteAsync();
            }
            catch (Exception)
            {
                throw;
            }
        }

        /// <summary>
        /// At the moment the only way to check if a file exists to catch an exception... :/
        /// </summary>
        /// <param name="fileName"></param>
        /// <returns></returns>
        protected async Task<StorageFile> GetFileIfExistsAsync(string fileName)
        {
            try
            {
                return await storageFolder.GetFileAsync(fileName);
            }
            catch
            {
                return null;
            }
        }

        /// <summary>
        /// Appends the file extension to the given filename
        /// </summary>
        /// <param name="fileName"></param>
        /// <returns></returns>
        protected string AppendExt(string fileName)
        {
            if (fileName.Contains(".txt"))
                return fileName;
            else
                return string.Format("{0}.txt", fileName);
        }

        /// <summary>
        /// Saves a serialized object to storage asynchronously
        /// </summary>
        /// <param name="filename"></param>
        /// <param name="obj"></param>
        public async void SaveAsync(string fileName, T data, string key = null)
        {
            try
            {
                if (data == null)
                    return;

                fileName = AppendExt(fileName);
                var file = await storageFolder.CreateFileAsync(fileName, CreationCollisionOption.ReplaceExisting);

                string serializedObject = JSONSerializerHelper.Serialize(data);
                string encryptedObject = serializedObject;

                if (key != null)
                {
                    encryptedObject = Hashing.Encrypt(serializedObject, key);
                }

                await FileIO.WriteTextAsync(file, encryptedObject);
            }
            catch (Exception)
            {
                throw;
            }
        }

        /// <summary>
        /// Load a given filename asynchronously
        /// </summary>
        /// <param name="fileName"></param>
        /// <returns></returns>
        public async Task<T> LoadAsync(string fileName, string key = null)
        {
            try
            {
                fileName = AppendExt(fileName);
                StorageFile file = null;
                file = await storageFolder.GetFileAsync(fileName);

                string serializedObject = await FileIO.ReadTextAsync(file);
                string decryptedObject = serializedObject;

                if (key != null)
                {
                    decryptedObject = Hashing.Decrypt(serializedObject, key);
                }

                return (T)JSONSerializerHelper.DeSerialize(typeof(T), decryptedObject);
            }
            catch (FileNotFoundException)
            {
                //file not existing is perfectly valid so simply return the default
                return default(T);
                //throw;
            }
            catch (Exception)
            {
                //Unable to load contents of file
                throw;
            }
        }
    }
}


For serializing data, I use Json.NET and create a helper for that:

using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace IsoStorageSample.Helpers
{
    public static class JSONSerializerHelper
    {
        public static string Serialize(object obj)
        {
            string json = JsonConvert.SerializeObject(obj, Formatting.Indented, new JsonSerializerSettings { PreserveReferencesHandling = PreserveReferencesHandling.Objects, TypeNameHandling = TypeNameHandling.Objects });
            return json;
        }

        public static object DeSerialize(Type type, string str)
        {
            object json = JsonConvert.DeserializeObject(str, type, new JsonSerializerSettings { PreserveReferencesHandling = PreserveReferencesHandling.Objects, TypeNameHandling = TypeNameHandling.Objects });
            return json;
        }
    }
}


And for hashing data I use Windows.Security.Cryptography

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Windows.Security.Cryptography;
using Windows.Security.Cryptography.Core;
using Windows.Storage.Streams;

namespace IsoStorageSample.Helpers
{
    public class Hashing
    {
        public static string Encrypt(string dataToEncrypt, string myKey)
        {
            //make sure we have data to work with
            if (string.IsNullOrEmpty(dataToEncrypt))
                throw new ArgumentException("input cannot be empty");

            if (string.IsNullOrEmpty(myKey))
                throw new ArgumentException("password cannot be empty");

            // get IV, key and encrypt
            var iv = CreateInitializationVector(myKey);
            var key = CreateKey(myKey);

            var encryptedBuffer = CryptographicEngine.Encrypt(key, CryptographicBuffer.ConvertStringToBinary(dataToEncrypt, BinaryStringEncoding.Utf8), iv);
            return CryptographicBuffer.EncodeToBase64String(encryptedBuffer);
        }

        public static string Decrypt(string encryptedString, string myKey)
        {
            try
            {
                //make sure we have data to work with
                if (string.IsNullOrEmpty(encryptedString))
                    throw new ArgumentException("input cannot be empty");

                if (string.IsNullOrEmpty(myKey))
                    throw new ArgumentException("password cannot be empty");

                // get IV, key and decrypt
                var iv = CreateInitializationVector(myKey);
                var key = CreateKey(myKey);

                var decryptedBuffer = CryptographicEngine.Decrypt(key, CryptographicBuffer.DecodeFromBase64String(encryptedString), iv);

                return CryptographicBuffer.ConvertBinaryToString(BinaryStringEncoding.Utf8, decryptedBuffer);
            }
            catch (Exception)
            {
                throw;
            }
        }

        private static IBuffer CreateInitializationVector(string password)
        {
            var provider = SymmetricKeyAlgorithmProvider.OpenAlgorithm("AES_CBC_PKCS7");
            var newPassword = password;

            // make sure we satify minimum length requirements
            while (newPassword.Length < provider.BlockLength)
            {
                newPassword = newPassword + password;
            }

            //create vecotr
            var iv = CryptographicBuffer.CreateFromByteArray(UTF8Encoding.UTF8.GetBytes(newPassword));
            return iv;
        }

        private static CryptographicKey CreateKey(string password)
        {
            var provider = SymmetricKeyAlgorithmProvider.OpenAlgorithm("AES_CBC_PKCS7");
            var newPassword = password;

            // make sure we satify minimum length requirements
            while (newPassword.Length < provider.BlockLength)
            {
                newPassword = newPassword + password;
            }

            var buffer = CryptographicBuffer.ConvertStringToBinary(newPassword, BinaryStringEncoding.Utf8);
            buffer.Length = provider.BlockLength;

            var key = provider.CreateSymmetricKey(buffer);
            return key;
        }
    }
}


Now we can use that like this:

private void SaveData()
{
    Dictionary<int, Person> persons = new Dictionary<int, Person>();

    persons.Add(1, new Person { ID = 1, Name = "Michael" });
    persons.Add(2, new Person { ID = 2, Name = "John" });
    persons.Add(3, new Person { ID = 3, Name = "Rose" });

    IsoStorage<Dictionary<int, Person>> storage = new IsoStorage<Dictionary<int, Person>>();

    //if key is not equal null => data will be encrypt
    storage.SaveAsync("TestStorage", persons, null);
}

private async void LoadData()
{
    IsoStorage<Dictionary<int, Person>> storage = new IsoStorage<Dictionary<int, Person>>();
    Dictionary<int, Person> persons = await storage.LoadAsync("TestStorage", null);
}

public class Person
{
    public int ID { get; set; }
    public string Name { get; set; }
}

Download full sample from here