Monday, December 9, 2013

Silverlight - Attached Property in Silverlight 5

An attached property is a concept defined by XAML. An attached property is intended to be used as a type of global property that is settable on any object. In Silverlight, attached properties are typically defined as a specialized form of dependency property that does not have the conventional property "wrapper".


Why and When we create an Attached Property???

One purpose of an attached property is to allow different child elements to specify unique values for a property that is actually defined in a parent element. A specific application of this scenario is having child elements inform the parent element of how they are to be presented in the user interface (UI).

You might create an attached property when there is a reason to have a property setting mechanism available for classes other than the defining class.

In this post i will show you how to create a Image Button using Attached Property in Silverlight 5.

Step 1
Create a Silverlight Application and give the solution name as SolImageButton_AP.



Click on Image for better view.

Select Silverlight Version.



Click on Image for better view.

Note : Select Web Project Type as ASP.NET Web site.

Step 2
Add the two Images in Solution it is look like this



Click on Image for better view.

Note :Download Source Code and you can get Images from Solution.

Step 3
Now we will create Attached Property for Button which add image on Button control.it is look like this.
using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;

namespace SolImageButton_AP
{
    public static class ImageButtonBehavior
    {
        #region (Step 1) Dependency Property Declaration 

        public static readonly DependencyProperty ImageButtonProperty = null;

        #endregion

        #region (Step 2) Register Dependency Property in Static Constructor

        static ImageButtonBehavior()
        {
            try
            {
                ImageButtonProperty=DependencyProperty.RegisterAttached("ImageButton",typeof(ImageSource),typeof(ImageButtonBehavior),new PropertyMetadata((ImageSource)null));
            }
            catch (Exception ex)
            {
                throw new Exception(ex.Message); 
            }
        }

        #endregion

        #region (Step 3) Get and Set Accessors static Method

        public static ImageSource GetImageButton(DependencyObject DoObj)
        {
            return DoObj.GetValue(ImageButtonProperty) as ImageSource;
        }

        public static void SetImageButton(DependencyObject DoObj, ImageSource ISObj)
        {
            DoObj.SetValue(ImageButtonProperty, ISObj);
        }

        #endregion
    }
}

Declare Dependency Property in static class.It is static because it describes a property that is valid for that class at all, not just for some specific instance of it.Register this Dependency Property in static Constructor.
At last define the get and set method inside the static class. These methods represent simple static type-safe wrappers for the GetValues and SetValue methods of the extended Dependency Object.Note that every attached property must have such methods defined because they are used by Silverlight when the value of the attached property should be changed from within XAML. The naming convention is pretty straightforward ‘Set + Property name’ and ‘Get + Property name’. 

Step 4
Mapping ImageButtonBehavior class in UserControl XAML,it is look like this
xmlns:Behavior="clr-namespace:SolImageButton_AP"

Finally it is look like on UserControl tag
<UserControl x:Class="SolImageButton_AP.MainPage"
 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"
 mc:Ignorable="d"
 xmlns:Behavior="clr-namespace:SolImageButton_AP"
 d:DesignHeight="300" d:DesignWidth="400">

</UserControl>

Step 5
Now add two Button control on Page,it is look like this
<Grid x:Name="LayoutRoot" Background="White">
      <StackPanel Orientation="Horizontal" HorizontalAlignment="Center">
         <Button Content="Save" Height="32" Width="100" Margin="10,0"/>
         <Button Content="Cancel" Height="32" Width="100" Margin="10,0"></Button>
      </StackPanel>
</Grid>


Click on Image for better view.

Step 6
Add the following code to define the style for button in UserControl.Resources,it is look like this
<UserControl.Resources>
   <DataTemplate x:Key="ImageButtonDataTemplate">
            <StackPanel Orientation="Horizontal">
                <Image Source="{Binding Path=(Behavior:ImageButtonBehavior.ImageButton),RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=Button}}" Stretch="Fill" Height="20" Width="20" HorizontalAlignment="Left" Margin="10,0,10,0"></Image>

                <TextBlock Text="{Binding Content, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=Button}}" HorizontalAlignment="Center" VerticalAlignment="Center"></TextBlock>
            </StackPanel>
    </DataTemplate>
    <Style x:Key="ImageButtonStyle" TargetType="Button">
 <Setter Property="HorizontalAlignment" Value="Stretch"/>
        <Setter Property="HorizontalContentAlignment" Value="Stretch"/>
        <Setter Property="ContentTemplate" Value="{StaticResource ImageButtonDataTemplate}"/>
    </Style>
</UserControl.Resources>

In here we have created style that we can place image along with button text using DataTemplate (ContentTemplate Property) of Button Control.

Step 7
Finally Set a ImageButton Attached Property and apply style to Button Control,it is look like this
<Grid x:Name="LayoutRoot" Background="White">
 <StackPanel Orientation="Horizontal" HorizontalAlignment="Center">
  <Button Content="Save" Height="32" Width="100" Margin="10,0" Behavior:ImageButtonBehavior.ImageButton="save.png" Style="{StaticResource ImageButtonStyle}"/>
                <Button Content="Cancel" Height="32" Width="100" Margin="10,0" Behavior:ImageButtonBehavior.ImageButton="cancel.png" Style="{StaticResource ImageButtonStyle}"></Button>
 </StackPanel>
</Grid>

Full XAML Code
<UserControl x:Class="SolImageButton_AP.MainPage"
 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"
 mc:Ignorable="d"
 xmlns:Behavior="clr-namespace:SolImageButton_AP"
 d:DesignHeight="300" d:DesignWidth="400">
    
 <UserControl.Resources>
  <DataTemplate x:Key="ImageButtonDataTemplate">
            <StackPanel Orientation="Horizontal">
                <Image Source="{Binding Path=(Behavior:ImageButtonBehavior.ImageButton),RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=Button}}" Stretch="Fill" Height="20" Width="20" HorizontalAlignment="Left" Margin="10,0,10,0"></Image>

                <TextBlock Text="{Binding Content, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=Button}}" HorizontalAlignment="Center" VerticalAlignment="Center"></TextBlock>
            </StackPanel>
        </DataTemplate>
  <Style x:Key="ImageButtonStyle" TargetType="Button">
   <Setter Property="HorizontalAlignment" Value="Stretch"/>
            <Setter Property="HorizontalContentAlignment" Value="Stretch"/>
            <Setter Property="ContentTemplate" Value="{StaticResource ImageButtonDataTemplate}"/>
        </Style>
 </UserControl.Resources>

 <Grid x:Name="LayoutRoot" Background="White">
  <StackPanel Orientation="Horizontal" HorizontalAlignment="Center">
   <Button Content="Save" Height="32" Width="100" Margin="10,0" Behavior:ImageButtonBehavior.ImageButton="save.png" Style="{StaticResource ImageButtonStyle}"/>
            <Button Content="Cancel" Height="32" Width="100" Margin="10,0" Behavior:ImageButtonBehavior.ImageButton="cancel.png" Style="{StaticResource ImageButtonStyle}"></Button>
  </StackPanel>
 </Grid>
</UserControl>

Run the Project.

Output


Download
Download Source Code

Sunday, November 24, 2013

LINQ - Custom Entity Class in Linq To SQL

In this article i will show you how to bind custom entity class to stored procedure result (DataContext Method) by using Linq to SQL.

The return type of a DataContext method (created based on a stored procedure or function) differs depending on where you drop the stored procedure or function in the O/R Designer.

There are two way to binding custom entity class to Stored Procedures result(DataContext Method). 

Method 1
First create a Custom entity class and drop stored procedure directly onto an Custom entity class, a DataContext method that has the return type of the custom entity class is created (if the schema of the data returned by the stored procedure or function matches the shape of the entity class). 

Method 2
If you drop an item onto an empty area of the O/R Designer, a DataContext method that returns an automatically generated type is created. You can change the return type of a DataContext method after you add it to the methods pane.change the return type of a DataContext method, select it and click the Return Type property in the Properties window.

Today i demonstrates second method.

Let see how can we bind custom entity class.

Step 1
Download Northwind database from the following link.
http://www.microsoft.com/downloads/details.aspx?FamilyID=06616212-0356-46a0-8da2-eebc53a68034&displaylang=en

Note : For SQL Server 2012 User,Download Northwind database from the following link
http://businessimpactinc.com/install-northwind-database/

Step 2
Attach Northwind database into MS-SQL server.

Note: For SQL Server 2012 User follow the instruction from above given website(Second Link) to attach database in MS-SQL Server 2012.

Step 3
Let's create a stored procedures which return the data,here we calculate count of per category of Products 
CREATE PROCEDURE [dbo].[SpGetProductCount]
AS

 SELECT Categories.CategoryName,COUNT(*) as 'ProductCount' 
  FROM Categories
   INNER JOIN
    Products
     ON Categories.CategoryID=Products.CategoryID
  GROUP BY Categories.CategoryName
  ORDER BY Categories.CategoryName ASC


Step 4
Create a ASP.net empty web site and give the solution name as SolCustomClass_LinqToSQL.

Step 5
Add App_Code folder in the solution and add a New Folder inside the App_Code folder and give folder name as ORD,it is look like this




Click on Image for better View

Step 6
Add a Linq to Sql class,Select the ORD folder,right click on Add new Item,select LINQ to SQL classes from installed Visual Studio templates and name it NorthwindDC and click on add button,it is look like this


Click on Image for better View

Step 7
Open a O/R Designer by double click on NorthwindDC.dbml,it is look like this



Click on Image for better View



Click on Image for better view.

Visual studio provides an object-relational mapping designer,called the O/R Designer which allows you to visually design the object to database mapping.

Step 8
To map stored procedure in DataContext class.go to the server explorer,select northwind database,go to the Stored Procedure and select SpGetProductCount stored procedure ,it is look like this



Click on Image for better view.

Drag and drop Stored Procedures from Server explorer onto the design surface of the O/R Designer,it is look like this



Click on Image for better view.

Step 9
Add a new Custom Entity class called CategorySummary using right click on O/R designer Panel,it is look like this



Click on Image for better view.

Add properties,Right click on class and Add Property,it is look like this



Click on Image for better view.

Here our Custom Entity Class ready
Click on Image for better view.

Now change the datatype of ProductCount Property from System.String to System.Int32,by default data type is System.String,Right Click on ProductCount Property and Select Properties.On Properties window,Select Type and change data type from String to Int,it is look like this



Click on Image for better view.

Step 10
Now bind the Stored Procedure with custom entity class,Right-click on the stored procedure and click on properties and select custom entity class name in ReturnType,it is look like this



Click on Image for better view.

Step 11
Create a Categories Static Class for calculate count of per category of Product,it is look like this
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;

/// <summary>
/// Summary description for Categories
/// </summary>
public static class Categories
{
    #region Method

    /// <summary>
    /// Get Count per category of Product
    /// </summary>
    /// <returns>List</returns>
    public static List<ORD.CategorySummary> GetProductCountData()
    {
        try
        {
            // Create a Instance of NorthwindDCDataContext
            ORD.NorthwindDCDataContext DC = new ORD.NorthwindDCDataContext();

            // return data
            return DC.SpGetProductCount().ToList<ORD.CategorySummary>();
        }
        catch (Exception ex)
        {
            throw new Exception(ex.Message); 
        }
    }

    #endregion
}

Step 12
Now Add a Default.aspx Page in the solution and drag and drop GridView Control on Page,it is look like this
<body>
    <form id="form1" runat="server">
    <div>
        <asp:GridView ID="gvProductCount" runat="server" AutoGenerateColumns="False" BackColor="White" BorderColor="#999999" BorderStyle="Solid" BorderWidth="1px" CellPadding="3" ForeColor="Black" GridLines="Vertical">
            <AlternatingRowStyle BackColor="#CCCCCC" />
            <Columns>
                <asp:BoundField DataField="CategoryName" HeaderText="Category Name" />
                <asp:BoundField DataField="ProductCount" HeaderText="ProductCount" />
            </Columns>
            <FooterStyle BackColor="#CCCCCC" />
            <HeaderStyle BackColor="Black" Font-Bold="True" ForeColor="White" />
            <PagerStyle BackColor="#999999" ForeColor="Black" HorizontalAlign="Center" />
            <SelectedRowStyle BackColor="#000099" Font-Bold="True" ForeColor="White" />
            <SortedAscendingCellStyle BackColor="#F1F1F1" />
            <SortedAscendingHeaderStyle BackColor="#808080" />
            <SortedDescendingCellStyle BackColor="#CAC9C9" />
            <SortedDescendingHeaderStyle BackColor="#383838" />
        </asp:GridView>
    </div>
    </form>
</body>


Click on Image for better view.

Step 13
Bind data to DataGrid View,it is look like this
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;

public partial class _Default : System.Web.UI.Page
{
    protected void Page_Load(object sender, EventArgs e)
    {
        if (IsPostBack == false)
        {
            try
            {
                BindGridView();
            }
            catch (Exception)
            { }
        }
    }

    #region  Method
    /// <summary>
    /// Bind Data to GridView
    /// </summary>
    private void BindGridView()
    {
        try
        {
            List<ORD.CategorySummary> ListObj = Categories.GetProductCountData();

            if (ListObj != null)
            {
                if (ListObj.Count >= 1)
                {
                    gvProductCount.DataSource = ListObj;
                    gvProductCount.DataBind();
                }
            }
        }
        catch (Exception ex)
        {
            throw new Exception(ex.Message); 
        }
    }

    #endregion
}

Run the Project.

Full .ASPX Code
<%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs" Inherits="_Default" %>

<!DOCTYPE html>

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title></title>
</head>
<body>
    <form id="form1" runat="server">
    <div>
        <asp:GridView ID="gvProductCount" runat="server" AutoGenerateColumns="False" BackColor="White" BorderColor="#999999" BorderStyle="Solid" BorderWidth="1px" CellPadding="3" ForeColor="Black" GridLines="Vertical">
            <AlternatingRowStyle BackColor="#CCCCCC" />
            <Columns>
                <asp:BoundField DataField="CategoryName" HeaderText="Category Name" />
                <asp:BoundField DataField="ProductCount" HeaderText="ProductCount" />
            </Columns>
            <FooterStyle BackColor="#CCCCCC" />
            <HeaderStyle BackColor="Black" Font-Bold="True" ForeColor="White" />
            <PagerStyle BackColor="#999999" ForeColor="Black" HorizontalAlign="Center" />
            <SelectedRowStyle BackColor="#000099" Font-Bold="True" ForeColor="White" />
            <SortedAscendingCellStyle BackColor="#F1F1F1" />
            <SortedAscendingHeaderStyle BackColor="#808080" />
            <SortedDescendingCellStyle BackColor="#CAC9C9" />
            <SortedDescendingHeaderStyle BackColor="#383838" />
        </asp:GridView>
    </div>
    </form>
</body>
</html>

Output

Click on Image for better view.

Download
Download Source Code

Sunday, November 17, 2013

WP8 - LongListSelector in Window Phone 8

In this article i will show you how to create Window 8 App Store(Metro) style dynamic Group Image Gallery using LongListSelector Control in Window Phone 8.

LongListSelector control provides a flexible way to display a collection of data in the form of a list or a grid.We can display data as grouped lists in LongListSelector Control. As the performance of LongListSelector is better than that of a ListBox and it also supports full data and UI virtualization.

In this example we display Images with names that are grouped by the first letter of the English name. When we click on a group header, a jump list with all letters of the alphabet appears, which the user can use to navigate to a particular group in the LongListSelector.

Lets create Window 8 Metro style group Image Gallery in Window Phone 8.

Step 1
Create a Window Phone Application and give the solution name as SolLongListSelector_WinPhone8.



Click on Image for better View

Note : Select a 4.5 Framework.

Step 2
Select Window Phone Platform,it is look like this



Click on Image for better View

Step 3
Create a New Folder in Solution and give folder name as Images,In that folder add images,it is look like this



Click on Image for better View

Step 4
Create a XML file in the solution and give the file name as ImageData.XML,it is look like this



Click on Image for better View

Step 5
The XML in the following example defines an XML document with a root node called Images. This root node contains one or more nodes called Image that include elements called English Name,Japanese Name and Image Path.
<?xml version="1.0" encoding="utf-8" ?>
<Images>

  <Image>
    <EnglishName>A</EnglishName>
    <JapaneseName>��</JapaneseName>
    <ImagePath>../Images/A.png</ImagePath>
  </Image>

  <Image>
    <EnglishName>Ao</EnglishName>
    <JapaneseName>�</JapaneseName>
    <ImagePath>../Images/Ao.png</ImagePath>
  </Image>

  <Image>
    <EnglishName>Aoba Yamashiro</EnglishName>
    <JapaneseName>山����</JapaneseName>
    <ImagePath>../Images/Aoba.png</ImagePath>
  </Image>

Continue........


</Images>

Note : Refer XML file from Solution.(Download Source Code and view XML file).

Step 6
Create a Image Entity class in the solution,it is look like this
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace SolLongListSelector_WinPhone8
{
    public class ImageEntity
    {
        #region Property

        public String EnglishName
        {
            get;
            set;
        }

        public String JapaneseName
        {
            get;
            set;
        }

        public String ImagePath
        {
            get;
            set;
        }

        #endregion
    }
}

Step 7
Create a KeyGroup class in the solution,it is look like this
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Globalization;
using Microsoft.Phone.Globalization;

namespace SolLongListSelector_WinPhone8
{
    public class KeyGroup<T> : List<T>
    {
        /// <summary>
        /// The Key of this group.
        /// </summary>
        public string Key { get; private set; }

        /// <summary>
        /// Public constructor.
        /// </summary>
        /// <param name="Key">The key for this group.</param>
        public KeyGroup(string Key)
        {
            this.Key = Key;
        }

        /// <summary>
        /// Create a list of AlphaGroup<T> with keys set by a SortedLocaleGrouping.
        /// </summary>
        /// <param name="slg">The </param>
        /// <returns>Theitems source for a LongListSelector</returns>
        private static List<KeyGroup<T>> CreateGroups(SortedLocaleGrouping SLGObj)
        {
            try
            {
                List<KeyGroup<T>> ListKGObj = new List<KeyGroup<T>>();

                foreach (string key in SLGObj.GroupDisplayNames)
                {
                    ListKGObj.Add(new KeyGroup<T>(key));
                }

                return ListKGObj;
            }
            catch (Exception ex)
            {
                throw new Exception(ex.Message); 
            }
        }

        /// <summary>
        /// Create a list of AlphaGroup<T> with keys set by a SortedLocaleGrouping.
        /// </summary>
        /// <param name="items">The items to place in the groups.</param>
        /// <param name="ci">The CultureInfo to group and sort by.</param>
        /// <param name="getKey">A delegate to get the key from an item.</param>
        /// <param name="sort">Will sort the data if true.</param>
        /// <returns>An items source for a LongListSelector</returns>
        public static List<KeyGroup<T>> CreateGroups(IEnumerable<T> Items, CultureInfo CIObj, Func<T,String> GetKey, bool Sort)
        {
            try
            {
                SortedLocaleGrouping SLGObj = new SortedLocaleGrouping(CIObj);

                List<KeyGroup<T>> ListKGObj = CreateGroups(SLGObj);

                foreach (T item in Items)
                {
                    int index = 0;
                    if (SLGObj.SupportsPhonetics)
                    {
                        //check if your database has yomi string for item
                        //if it does not, then do you want to generate Yomi or ask the user for this item.
                        //index = slg.GetGroupIndex(getKey(Yomiof(item)));
                    }
                    else
                    {
                        index = SLGObj.GetGroupIndex(GetKey(item));
                    }
                    if (index >= 0 && index < ListKGObj.Count)
                    {
                        ListKGObj[index].Add(item);
                    }
                }

                if (Sort)
                {
                    foreach (KeyGroup<T> group in ListKGObj)
                    {
                        group.Sort((c0, c1) => { return CIObj.CompareInfo.Compare(GetKey(c0), GetKey(c1)); });
                    }
                }

                return ListKGObj;
            }
            catch (Exception ex) 
            {
                throw new Exception(ex.Message); 
            }
        }

    }
}

KeyGroup is a helper class that is used to convert a flat list of data into a grouped list in which the entries are grouped by a key. In this example we use this class to convert a flat list of Images Data to a list of lists that is grouped by the first letter of the English name.

Step 8
Create an ImageView class in the solution for retrieving Data from XML document,it is look like this
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Xml;
using System.Xml.Linq;

namespace SolLongListSelector_WinPhone8
{
    public static class ImageView
    {
        #region Method

        /// <summary>
        /// Group Image Data
        /// </summary>
        /// <returns>List</returns>
        public static Task<List<KeyGroup<ImageEntity>>> GetGroupImageData()
        {
            try
            {
                return Task.Run<List<KeyGroup<ImageEntity>>>(() =>
                {
                    // Load XML Document
                    XDocument XDoc = XDocument.Load("ImageData.xml");

                    // Get All data from XML Document
                    var Query = (from Q in XDoc.Descendants("Image")
                                 select new ImageEntity
                                 {
                                     EnglishName = Q.Element("EnglishName").Value,
                                     JapaneseName = Q.Element("JapaneseName").Value,
                                     ImagePath = Q.Element("ImagePath").Value
                                 }).ToList<ImageEntity>();

                    // Grouped Data
                    return KeyGroup<ImageEntity>.CreateGroups(Query, System.Threading.Thread.CurrentThread.CurrentUICulture, (ImageEntity IE) => { return IE.EnglishName; }, true);

                });
            }

            catch (Exception ex)
            {
                throw new Exception(ex.Message); 
            }
        }

        #endregion
    }
}

Step 9
In MainPage.XAML drag and drop a LongListSelector Control from Control Toolbox,it is look like this
<Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
   <phone:LongListSelector x:Name="LLSImageGallery" LayoutMode="Grid" GridCellSize="220,220"  IsGroupingEnabled="True" HideEmptyGroups="True" HorizontalAlignment="Stretch"  VerticalAlignment="Stretch"  VirtualizingStackPanel.VirtualizationMode="Recycling"/>

   

</Grid>

In this code, LayoutMode is set to Grid, which means that the Images Data are laid out in grid format.GridCellSize Indicates the size of each cell in the grid The IsGroupingEnabled is set to true to group the displayed items, and the HideEmptyGroups is set to true, which means that if a group does not have any items in it, it will not be displayed.The VirtualizingStackPanel.VirtualizationMode Attached Property is set Recycling,Which means the VirtualizingStackPanel reuses item containers instead of creating a new one each time.

Step 10
Add the following code to define a DataTemplate for display Images with Names in phone:PhoneApplicationPage.Resources,it is look like this
<phone:PhoneApplicationPage.Resources>
  <DataTemplate x:Key="LLSItemDataTemplate">
   <Grid>
    
    <Border Background="Transparent" Padding="5">
     <Image Source="{Binding ImagePath}" Stretch="Fill" HorizontalAlignment="Stretch"  VerticalAlignment="Center"></Image>
    </Border>
    
    <StackPanel VerticalAlignment="Bottom" Background="Black" Opacity="0.70" Width="Auto">
     <TextBlock Text="{Binding EnglishName}" Foreground="White" Height="30" FontWeight="SemiBold" HorizontalAlignment="Left" Margin="10,0,0,0"/>
     <TextBlock Text="{Binding JapaneseName}" Foreground="White" Height="30" FontWeight="SemiBold" HorizontalAlignment="Right" Margin="0,0,10,0"/>
    </StackPanel>
   
   </Grid>
  </DataTemplate>

</phone:PhoneApplicationPage.Resources>

Step 11
Add the following code to define DataTemplate for the group header in phone:PhoneApplicationPage.Resources,it is look like this.
<phone:PhoneApplicationPage.Resources>
  <DataTemplate x:Key="LLSHeaderDataTemplate">
   <Grid Background="Transparent">
    
    <Border Background="Red">
     <TextBlock Text="{Binding Key}" Foreground="White" FontSize="30" FontWeight="Bold" HorizontalAlignment="Center" VerticalAlignment="Center" />
    </Border>
    
   </Grid>
  </DataTemplate>
</phone:PhoneApplicationPage.Resources>

The DataTemplate will display the First Character of English Name(in our case Key Property in KeyGroup Class)

Step 12
Add the following code to define the jump list style in phone:PhoneApplicationPage.Resources.
<phone:PhoneApplicationPage.Resources>
  
  <phone:JumpListItemBackgroundConverter x:Key="BackgroundConverter"/>
  <phone:JumpListItemForegroundConverter x:Key="ForegroundConverter"/>
  <Style x:Key="LLSJumpListStyle" TargetType="phone:LongListSelector">
     <Setter Property="GridCellSize"  Value="113,113"/>
     <Setter Property="LayoutMode" Value="Grid" />
     <Setter Property="ItemTemplate">
     <Setter.Value>
     <DataTemplate>
      
     <Border Background="{Binding Converter={StaticResource BackgroundConverter}}" Width="113" Height="113" Margin="6" >
        <TextBlock Text="{Binding Key}" FontFamily="{StaticResource PhoneFontFamilySemiBold}" FontSize="48" Padding="6" 
        Foreground="{Binding Converter={StaticResource ForegroundConverter}}" VerticalAlignment="Center"   UseLayoutRounding="False"/>
     </Border>
      
     </DataTemplate>
      </Setter.Value>
   </Setter>
  </Style>
  
 </phone:PhoneApplicationPage.Resources>

Finally  phone:PhoneApplicationPage.Resources look like this
<phone:PhoneApplicationPage.Resources>
  <DataTemplate x:Key="LLSItemDataTemplate">
   <Grid>
    
    <Border Background="Transparent" Padding="5">
     <Image Source="{Binding ImagePath}" Stretch="Fill" HorizontalAlignment="Stretch"  VerticalAlignment="Center"></Image>
    </Border>
    
    <StackPanel VerticalAlignment="Bottom" Background="Black" Opacity="0.70" Width="Auto">
     <TextBlock Text="{Binding EnglishName}" Foreground="White" Height="30" FontWeight="SemiBold" HorizontalAlignment="Left" Margin="10,0,0,0"/>
     <TextBlock Text="{Binding JapaneseName}" Foreground="White" Height="30" FontWeight="SemiBold" HorizontalAlignment="Right" Margin="0,0,10,0"/>
    </StackPanel>
   
   </Grid>
  </DataTemplate>
  
  <DataTemplate x:Key="LLSHeaderDataTemplate">
   <Grid Background="Transparent">
    
    <Border Background="Red">
     <TextBlock Text="{Binding Key}" Foreground="White" FontSize="30" FontWeight="Bold" HorizontalAlignment="Center" VerticalAlignment="Center" />
    </Border>
    
   </Grid>
  </DataTemplate>

  <phone:JumpListItemBackgroundConverter x:Key="BackgroundConverter"/>
  <phone:JumpListItemForegroundConverter x:Key="ForegroundConverter"/>
  <Style x:Key="LLSJumpListStyle" TargetType="phone:LongListSelector">
     <Setter Property="GridCellSize"  Value="113,113"/>
     <Setter Property="LayoutMode" Value="Grid" />
     <Setter Property="ItemTemplate">
     <Setter.Value>
     <DataTemplate>
      
     <Border Background="{Binding Converter={StaticResource BackgroundConverter}}" Width="113" Height="113" Margin="6" >
        <TextBlock Text="{Binding Key}" FontFamily="{StaticResource PhoneFontFamilySemiBold}" FontSize="48" Padding="6" 
        Foreground="{Binding Converter={StaticResource ForegroundConverter}}" VerticalAlignment="Center"   UseLayoutRounding="False"/>
     </Border>
      
     </DataTemplate>
      </Setter.Value>
   </Setter>
  </Style>
  
 </phone:PhoneApplicationPage.Resources>

Step 13
Now apply this above templates and JumpListStyle in LongListSelector Control,it is look like this
<Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
            <phone:LongListSelector x:Name="LLSImageGallery" LayoutMode="Grid" GridCellSize="220,220"  IsGroupingEnabled="True" HideEmptyGroups="True"   HorizontalAlignment="Stretch"  VerticalAlignment="Stretch"  VirtualizingStackPanel.VirtualizationMode="Recycling" ItemsSource="{Binding}" ItemTemplate="{StaticResource LLSItemDataTemplate}" GroupHeaderTemplate="{StaticResource LLSHeaderDataTemplate}" JumpListStyle="{StaticResource LLSJumpListStyle}"/>

   

  </Grid>

Full XAML Code
<phone:PhoneApplicationPage
 x:Class="SolLongListSelector_WinPhone8.MainPage"
 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
 xmlns:phone="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone"
 xmlns:shell="clr-namespace:Microsoft.Phone.Shell;assembly=Microsoft.Phone"
 xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
 xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
 mc:Ignorable="d"
 FontFamily="{StaticResource PhoneFontFamilyNormal}"
 FontSize="{StaticResource PhoneFontSizeNormal}"
 Foreground="{StaticResource PhoneForegroundBrush}"
 SupportedOrientations="Portrait" Orientation="Portrait"
 shell:SystemTray.IsVisible="True">
 
 <phone:PhoneApplicationPage.Resources>
  <DataTemplate x:Key="LLSItemDataTemplate">
   <Grid>
    
    <Border Background="Transparent" Padding="5">
     <Image Source="{Binding ImagePath}" Stretch="Fill" HorizontalAlignment="Stretch"  VerticalAlignment="Center"></Image>
    </Border>
    
    <StackPanel VerticalAlignment="Bottom" Background="Black" Opacity="0.70" Width="Auto">
     <TextBlock Text="{Binding EnglishName}" Foreground="White" Height="30" FontWeight="SemiBold" HorizontalAlignment="Left" Margin="10,0,0,0"/>
     <TextBlock Text="{Binding JapaneseName}" Foreground="White" Height="30" FontWeight="SemiBold" HorizontalAlignment="Right" Margin="0,0,10,0"/>
    </StackPanel>
   
   </Grid>
  </DataTemplate>
  
  <DataTemplate x:Key="LLSHeaderDataTemplate">
   <Grid Background="Transparent">
    
    <Border Background="Red">
     <TextBlock Text="{Binding Key}" Foreground="White" FontSize="30" FontWeight="Bold" HorizontalAlignment="Center" VerticalAlignment="Center" />
    </Border>
    
   </Grid>
  </DataTemplate>

  <phone:JumpListItemBackgroundConverter x:Key="BackgroundConverter"/>
  <phone:JumpListItemForegroundConverter x:Key="ForegroundConverter"/>
  <Style x:Key="LLSJumpListStyle" TargetType="phone:LongListSelector">
     <Setter Property="GridCellSize"  Value="113,113"/>
     <Setter Property="LayoutMode" Value="Grid" />
     <Setter Property="ItemTemplate">
     <Setter.Value>
     <DataTemplate>
      
     <Border Background="{Binding Converter={StaticResource BackgroundConverter}}" Width="113" Height="113" Margin="6" >
        <TextBlock Text="{Binding Key}" FontFamily="{StaticResource PhoneFontFamilySemiBold}" FontSize="48" Padding="6" 
        Foreground="{Binding Converter={StaticResource ForegroundConverter}}" VerticalAlignment="Center"   UseLayoutRounding="False"/>
     </Border>
      
     </DataTemplate>
      </Setter.Value>
   </Setter>
  </Style>
  
 </phone:PhoneApplicationPage.Resources>

 <!--LayoutRoot is the root grid where all page content is placed-->
 <Grid x:Name="LayoutRoot" Background="Transparent">
  <Grid.RowDefinitions>
   <RowDefinition Height="Auto"/>
   <RowDefinition Height="*"/>
  </Grid.RowDefinitions>

  <!-- LOCALIZATION NOTE:
   To localize the displayed strings copy their values to appropriately named
   keys in the app's neutral language resource file (AppResources.resx) then
   replace the hard-coded text value between the attributes' quotation marks
   with the binding clause whose path points to that string name.

   For example:

    Text="{Binding Path=LocalizedResources.ApplicationTitle, Source={StaticResource LocalizedStrings}}"

   This binding points to the template's string resource named "ApplicationTitle".

   Adding supported languages in the Project Properties tab will create a
   new resx file per language that can carry the translated values of your
   UI strings. The binding in these examples will cause the value of the
   attributes to be drawn from the .resx file that matches the
   CurrentUICulture of the app at run time.
   -->

  <!--TitlePanel contains the name of the application and page title-->
  <StackPanel x:Name="TitlePanel" Grid.Row="0" Margin="12,17,0,28">
   <TextBlock Text="Image Gallery Using LongListSelector Control" Style="{StaticResource PhoneTextNormalStyle}" Margin="12,0"/>
  </StackPanel>

  <!--ContentPanel - place additional content here-->
  <Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
            <phone:LongListSelector x:Name="LLSImageGallery" LayoutMode="Grid" GridCellSize="220,220"  IsGroupingEnabled="True" HideEmptyGroups="True"   HorizontalAlignment="Stretch"  VerticalAlignment="Stretch"  VirtualizingStackPanel.VirtualizationMode="Recycling" ItemsSource="{Binding}" ItemTemplate="{StaticResource LLSItemDataTemplate}" GroupHeaderTemplate="{StaticResource LLSHeaderDataTemplate}" JumpListStyle="{StaticResource LLSJumpListStyle}"/>

   

  </Grid>

  <!--Uncomment to see an alignment grid to help ensure your controls are
   aligned on common boundaries.  The image has a top margin of -32px to
   account for the System Tray. Set this to 0 (or remove the margin altogether)
   if the System Tray is hidden.

   Before shipping remove this XAML and the image itself.-->
  <!--<Image Source="/Assets/AlignmentGrid.png" VerticalAlignment="Top" Height="800" Width="480" Margin="0,-32,0,0" Grid.Row="0" Grid.RowSpan="2" IsHitTestVisible="False" />-->
 </Grid>

</phone:PhoneApplicationPage>

Step 14
In Code Behind,On Page Load event Bind the data to LongListSelector Control,it is look like this
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Navigation;
using Microsoft.Phone.Controls;
using Microsoft.Phone.Shell;
using SolLongListSelector_WinPhone8.Resources;

namespace SolLongListSelector_WinPhone8
{
    public partial class MainPage : PhoneApplicationPage
    {
        // Constructor
        public MainPage()
        {
            InitializeComponent();

            // Sample code to localize the ApplicationBar
            //BuildLocalizedApplicationBar();

            this.Loaded += async (s, o) => {
                try
                {
                    List<KeyGroup<ImageEntity>> ListImageObj = await ImageView.GetGroupImageData();

                    if (ListImageObj != null)
                    {
                        if (ListImageObj.Count >= 1)
                        {
                            // Bind Data to the LongListSelector Control
                            LLSImageGallery.DataContext = ListImageObj;
                        }
                    }
                }
                catch (Exception ex)
                {
                    MessageBox.Show(ex.Message); 
                }
            };
        }

        // Sample code for building a localized ApplicationBar
        //private void BuildLocalizedApplicationBar()
        //{
        //    // Set the page's ApplicationBar to a new instance of ApplicationBar.
        //    ApplicationBar = new ApplicationBar();

        //    // Create a new button and set the text value to the localized string from AppResources.
        //    ApplicationBarIconButton appBarButton = new ApplicationBarIconButton(new Uri("/Assets/AppBar/appbar.add.rest.png", UriKind.Relative));
        //    appBarButton.Text = AppResources.AppBarButtonText;
        //    ApplicationBar.Buttons.Add(appBarButton);

        //    // Create a new menu item with the localized string from AppResources.
        //    ApplicationBarMenuItem appBarMenuItem = new ApplicationBarMenuItem(AppResources.AppBarMenuItemText);
        //    ApplicationBar.MenuItems.Add(appBarMenuItem);
        //}
    }
}

Run the Project.

Output



Click on Image for better view

Click on a group header, a jump list with all letters of the alphabet appears



Click on Image for better view

Navigate to a particular group (Click on M group)



Click on Image for better view

Download
Download Source Code

Monday, November 11, 2013

Win 8 - Image Gallery in Window 8 App

In this article i will show you how to display dynamic Group Image Gallery in Window 8 Store App by using GridView Control.

GridViews are often used to hold groups of collections, rather than simple collections.  The GridView template assumes that it will be displaying groups of collections of items, and this can make working with the GridView.

Step 1
Create a Window Store Application and give the solution name as SolImageGallery_Win8App.



Click on Image for better View

Note : Select a 4.5 Framework.

Step 2
Create a New Folder in Solution and give folder name as Images,In that folder add images,it is look like this



Click on Image for better View

Step 3
Create a XML file in the solution and give the file name as ImageData.XML,it is look like this



Click on Image for better View

Step 4
The XML in the following example defines an XML document with a root node called Images. This root node contains one or more nodes called Image that include elements called English Name,Japanese Name and Image Path.
<?xml version="1.0" encoding="utf-8" ?>
<Images>

  <Image>
    <EnglishName>A</EnglishName>
    <JapaneseName>��</JapaneseName>
    <ImagePath>../Images/A.png</ImagePath>
  </Image>

  <Image>
    <EnglishName>Ao</EnglishName>
    <JapaneseName>�</JapaneseName>
    <ImagePath>../Images/Ao.png</ImagePath>
  </Image>

  <Image>
    <EnglishName>Aoba Yamashiro</EnglishName>
    <JapaneseName>山����</JapaneseName>
    <ImagePath>../Images/Aoba.png</ImagePath>
  </Image>

Continue........


</Images>

Note : Refer XML file from Solution.(Download Source Code and view XML file).

Step 5
Create a Image Entity class in the solution,it is look like this
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace SolImageGallery_Win8App
{
    public class ImageEntity
    {
        #region Property

        public String EnglishName
        {
            get;
            set;
        }

        public String JapaneseName
        {
            get;
            set;
        }

        public String ImagePath
        {
            get;
            set;
        }

        #endregion
    }
}

Step 6
Create a KeyGroup class in the solution,it is look like this
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace SolImageGallery_Win8App
{
    public class KeyGroup<TKey,TItems>
    {
        #region Property

        public TKey Key
        {
            get;
            set;
        }

        public IList<TItems> Items
        {
            get;
            set;
        }

        #endregion
    }
}

I would like to display images with names in a GridView,but Grouped by first character of English Name.The trick is a create a KeyGroup class that will allow you to have a Key on which you group the first character of English Name and list of images who match that key.

Step 7
Create an ImageView class in the solution for retrieving Data from XML document,it is look like this
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Xml;
using System.Xml.Linq;

namespace SolImageGallery_Win8App
{
    public static class ImageView
    {
        #region Method

        /// <summary>
        /// Group Image Data
        /// </summary>
        /// <returns>List</returns>
        public static Task<List<KeyGroup<Char, ImageEntity>>> GetGroupImageData()
        {
            try
            {
                return Task.Run<List<KeyGroup<Char, ImageEntity>>>(() => {

                    XDocument XDoc = XDocument.Load("ImageData.xml");

                    // Using Linq Query

                    // First Get All Values from XML file
                    //var QueryImageData = from Q in XDoc.Descendants("Image")
                    //                     select new ImageEntity
                    //                     {
                    //                         EnglishName = Q.Element("EnglishName").Value,
                    //                         JapaneseName = Q.Element("JapaneseName").Value,
                    //                         ImagePath = Q.Element("ImagePath").Value
                    //                     };

                    // Now Group By First Character of English Name and bind this data to KeyGroup Class
                    //var GroupImageQuery =(from Q in QueryImageData
                    //                      group Q by Q.EnglishName.Cast<char>().First() into GB
                    //                      orderby GB.Key
                    //                      select new KeyGroup<Char, ImageEntity>()
                    //                      {
                    //                          Key = GB.Key,
                    //                          Items = GB.ToList()
                    //                      }).ToList();

                    //return GroupImageQuery;

                    // Using Lambda Expression

                    return XDoc.Descendants("Image").Select(LE => new ImageEntity()
                    {
                        EnglishName = LE.Element("EnglishName").Value,
                        JapaneseName = LE.Element("JapaneseName").Value,
                        ImagePath = LE.Element("ImagePath").Value
                    }).ToList().GroupBy(GB => GB.EnglishName.Cast<Char>().First()).OrderBy(OB => OB.Key).Select(KG => new KeyGroup<Char, ImageEntity>()
                    {
                        Key = KG.Key,
                        Items = KG.ToList()
                    }).ToList();

                });
            }
            catch (Exception ex)
            {
                throw new Exception(ex.Message); 
            }
        }

        #endregion
    }
}

Step 8
In MainPage.XAML add a GridView Control,it is look like this
<Grid Background="{StaticResource ApplicationPageBackgroundThemeBrush}">
        <GridView x:Name="gvImageGallery" SelectionMode="None" VirtualizingStackPanel.VirtualizationMode="Recycling">

        </GridView>
</Grid>

Step 9
Create a CollectionViewSource in Page.Resources ,it is look like this
<Page.Resources>
        <CollectionViewSource x:Name="CVS_ImageGallery" IsSourceGrouped="True" ItemsPath="Items" VirtualizingStackPanel.VirtualizationMode="Recycling"></CollectionViewSource>
    
 </Page.Resources>

The CollectionViewSource manages the collection of lists, and is created in the Resources Section.  Set the IsSourceGrouped property to True and set the ItemsPath to the list of objects (in our case, the Items property in the  KeyGroup class.)

Step 10
Add the following code to define a DataTemplate for display Images with Names and ItemsPanelTemplate for defines the panel that controls the layout of items  in Page.Resources,it is look like this
<Page.Resources>
        <CollectionViewSource x:Name="CVS_ImageGallery" IsSourceGrouped="True" ItemsPath="Items" VirtualizingStackPanel.VirtualizationMode="Recycling"></CollectionViewSource>
        
        <ItemsPanelTemplate x:Key="ImageGalleryItemsPanelTemplate">
            
            <VirtualizingStackPanel Orientation="Horizontal" VirtualizingStackPanel.VirtualizationMode="Recycling"></VirtualizingStackPanel>
        
        </ItemsPanelTemplate>

        <DataTemplate x:Key="ImageGalleryDataTemplate">
         <Grid HorizontalAlignment="Left" Width="250" Height="250">
                
                <Border Background="{StaticResource ListViewItemPlaceholderBackgroundThemeBrush}">
                    <Image Source="{Binding ImagePath}" Stretch="Fill"  AutomationProperties.Name="{Binding EnglishName}"> </Image>
                </Border>
                
                <StackPanel VerticalAlignment="Bottom" Background="{StaticResource ListViewItemOverlayBackgroundThemeBrush}">
                    <TextBlock Text="{Binding EnglishName}" Foreground="{StaticResource ListViewItemOverlayForegroundThemeBrush}" Style="{StaticResource TitleTextStyle}" Height="30" Margin="15,0,15,0"/>
                    <TextBlock Text="{Binding JapaneseName}" Foreground="{StaticResource ListViewItemOverlayForegroundThemeBrush}" Style="{StaticResource TitleTextStyle}" Height="30" HorizontalAlignment="Right" Margin="0,0,15,0"/>
                </StackPanel>
            
            </Grid>
        </DataTemplate>
       
    </Page.Resources>

Step 11
Now apply this above templates and CollectionViewSource to the Gridview Control it is like this
<GridView x:Name="gvImageGallery" SelectionMode="None"  ItemsSource="{Binding Source={StaticResource ResourceKey=CVS_ImageGallery}}" ItemsPanel="{StaticResource ImageGalleryItemsPanelTemplate}" ItemTemplate="{StaticResource ImageGalleryDataTemplate}" VirtualizingStackPanel.VirtualizationMode="Recycling">

</GridView>

Step 12
Finally Add a GridView GroupStyle,it is look like this
<GridView x:Name="gvImageGallery" SelectionMode="None"  ItemsSource="{Binding Source={StaticResource ResourceKey=CVS_ImageGallery}}" ItemsPanel="{StaticResource ImageGalleryItemsPanelTemplate}" ItemTemplate="{StaticResource ImageGalleryDataTemplate}" VirtualizingStackPanel.VirtualizationMode="Recycling">
            <GridView.GroupStyle>
                <GroupStyle>
                    <GroupStyle.HeaderTemplate>
                        <DataTemplate>
                            <Grid Background="{StaticResource ApplicationPageBackgroundThemeBrush}">
                                
                                <TextBlock Text='{Binding Key}' Foreground="Orange" FontSize="30" Margin="25,0" FontWeight="Bold" />
                            
                            </Grid>
                        </DataTemplate>
                    </GroupStyle.HeaderTemplate>
                    <GroupStyle.Panel>
                        <ItemsPanelTemplate>
                            
                            <VariableSizedWrapGrid Orientation="Vertical"  MaximumRowsOrColumns="2" Margin="25,0" />
                        
                        </ItemsPanelTemplate>
                    </GroupStyle.Panel>
                </GroupStyle>
            </GridView.GroupStyle>
           
        </GridView>

In GridView GroupStyle there are two templates,One for header and another for items.The HeaderTemplate will display the First Character of English Name(in our case Key Property in KeyGroup Class) and ItemsPanelTemplate that creates layout of Items.  

Full XAML Code
<Page
    x:Class="SolImageGallery_Win8App.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:SolImageGallery_Win8App"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d">
    
    <Page.Resources>
        <CollectionViewSource x:Name="CVS_ImageGallery" IsSourceGrouped="True" ItemsPath="Items" VirtualizingStackPanel.VirtualizationMode="Recycling"></CollectionViewSource>
        
        <ItemsPanelTemplate x:Key="ImageGalleryItemsPanelTemplate">
            
            <VirtualizingStackPanel Orientation="Horizontal" VirtualizingStackPanel.VirtualizationMode="Recycling"></VirtualizingStackPanel>
        
        </ItemsPanelTemplate>

        <DataTemplate x:Key="ImageGalleryDataTemplate">
         <Grid HorizontalAlignment="Left" Width="250" Height="250">
                
                <Border Background="{StaticResource ListViewItemPlaceholderBackgroundThemeBrush}">
                    <Image Source="{Binding ImagePath}" Stretch="Fill"  AutomationProperties.Name="{Binding EnglishName}"> </Image>
                </Border>
                
                <StackPanel VerticalAlignment="Bottom" Background="{StaticResource ListViewItemOverlayBackgroundThemeBrush}">
                    <TextBlock Text="{Binding EnglishName}" Foreground="{StaticResource ListViewItemOverlayForegroundThemeBrush}" Style="{StaticResource TitleTextStyle}" Height="30" Margin="15,0,15,0"/>
                    <TextBlock Text="{Binding JapaneseName}" Foreground="{StaticResource ListViewItemOverlayForegroundThemeBrush}" Style="{StaticResource TitleTextStyle}" Height="30" HorizontalAlignment="Right" Margin="0,0,15,0"/>
                </StackPanel>
            
            </Grid>
        </DataTemplate>
       
    </Page.Resources>
    

    <Grid Background="{StaticResource ApplicationPageBackgroundThemeBrush}">
        <GridView x:Name="gvImageGallery" SelectionMode="None"  ItemsSource="{Binding Source={StaticResource ResourceKey=CVS_ImageGallery}}" ItemsPanel="{StaticResource ImageGalleryItemsPanelTemplate}" ItemTemplate="{StaticResource ImageGalleryDataTemplate}" VirtualizingStackPanel.VirtualizationMode="Recycling">
            <GridView.GroupStyle>
                <GroupStyle>
                    <GroupStyle.HeaderTemplate>
                        <DataTemplate>
                            <Grid Background="{StaticResource ApplicationPageBackgroundThemeBrush}">
                                
                                <TextBlock Text='{Binding Key}' Foreground="Orange" FontSize="30" Margin="25,0" FontWeight="Bold" />
                            
                            </Grid>
                        </DataTemplate>
                    </GroupStyle.HeaderTemplate>
                    <GroupStyle.Panel>
                        <ItemsPanelTemplate>
                            
                            <VariableSizedWrapGrid Orientation="Vertical"  MaximumRowsOrColumns="2" Margin="25,0" />
                        
                        </ItemsPanelTemplate>
                    </GroupStyle.Panel>
                </GroupStyle>
            </GridView.GroupStyle>
           
        </GridView>
    </Grid>
</Page>

Step 13
In Code Behind,On Page Load event Bind the data to CollectionViewSource,it is look like this
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using Windows.Foundation;
using Windows.Foundation.Collections;
using Windows.UI.Popups;
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;
using Windows.Storage;

// The Blank Page item template is documented at http://go.microsoft.com/fwlink/?LinkId=234238

namespace SolImageGallery_Win8App
{
    /// <summary>
    /// An empty page that can be used on its own or navigated to within a Frame.
    /// </summary>
    public sealed partial class MainPage : Page
    {
        public MainPage()
        {
            this.InitializeComponent();

            this.Loaded += async (s, o) => {

                List<KeyGroup<Char, ImageEntity>> ListObj = await ImageView.GetGroupImageData();

                if (ListObj != null)
                {
                    if (ListObj.Count >= 1)
                    {
                        CVS_ImageGallery.Source = await ImageView.GetGroupImageData();
                    }
                }
            };
        }

        /// <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)
        {
        }
    }
}

Run the Project.

Output



Click on Image for better View

On Simulator



Click on Image for better View

Download
Download Source Code

I had a Created another Simple Image Gallery.

Output



Click on Image for better View

Download
Download Source Code