Showing posts with label xaml. Show all posts
Showing posts with label xaml. Show all posts

Wednesday, 30 January 2013

Layout : Xaml

If you are familiar with Silverlight , WPF Xaml , you may find this blog very basic.
If you are new to Windows 8 app/phone app development and want to understand UI layouts then you are at the right place.

What do you mean by UI Layout?

In my last article I explained containers. Containers tell you how your controls are held on the UI , layout defines how the containers or the controls inside the containers are positioned.

If layout of your application is proper , the UI is not going to get distorted on different devices and different resolutions. The main concept of Windows 8 was Develop Once and Port anywhere. For this porting to happen smoothly we need to be careful enough when we are selecting layout of the xaml page.

For a canvas container you always define the controls at their absolute positions , for a grid/stack panel you define the controls in a relative manner.

So , if your app is targeted towards various devices the best I will suggest is grid and stackpanel.

Now that we are settled with the grid/stack panel as container , let us think on how to position them.

Windows 8 Phone/App supports two types of layout.
a. Absolute Layout
b. Dynamic Layout

Absolute layout should be used when you can define the absolute positions of the controls. That is you define exact locations of all your child elements relative to the parent.If the app requires absolute positioning of UI elements, you can design different pages for different screen resolutions or use scaling as an alternative.

By default the layout is absolute and container is grid for a Windows 8 app.

Dynamic Layout:

You specify the relative positions for all your controls.To use automatic or proportional sizing, you must assign special values to the Height and Width properties.

Microsoft recommends following for a dynamic layout:
(Following lines are taken as is from msdn)

  • Set the Height and Width of the control or layout to Auto. When these values are used for controls in the Grid layout, the control fills the cell that contains it. Auto sizing is supported for controls and for the Grid and StackPanel layouts.

  • For controls that contain text, remove the Height and Width properties, and set the MinWidth or MinHeight properties. This prevents the text from scaling down to a size that's unreadable.

  • To set proportional values for the RowDefinition and ColumnDefinition elements in a Grid layout, use relative Height and Width values. For example, to specify that one column is five times wider than another column, use "*" and "5*" for the Width properties in the ColumnDefinition elements. 

Conclusion:
If you have a screen that should readjust itself based on reolutions my suggestion is use Grid with Dynamic layout.

Conatainer Panels in XAML

Container Panels for XAML:

a. Canvas
b. Stack Panel
c. Grid

The above containers can be used both in Windows 8 and Windows 8 Phones as well.
If you are a Silverlight/WPF developer , you will not find these new , but in case you are into xaml development for the first time. Here is a brief description of these panels for you.

Canvas :


Defines an area within which you can explicitly position child objects by using coordinates that are relative to the area.
A Canvas is one of the Panel elements that enable layout. Each child object is rendered within the Canvas area.
The controls are specified inside a canvas using the x and y positions.
The positions are defined in logical pixels.
The x and y coordinates are often specified by using the Canvas.Left and Canvas.Top attached properties.
A Canvas can contain nested objects.
When objects are placed inside the canvas they are positioned relative to the canvas.Only UIElements can be put inside the canvas tags.
You can nest Canvas objects, because a Canvas is a type of UIElement.
In many cases, a Canvas is used solely as a container for other objects and does not have any visible properties.
You can control the visibility of a canavas by using height/width/Background/Opcaity/Visibility/Ancestor Objects.


Stack Panel :


StackPanel is one of the Panel elements that enable layout.
Stack panels help arranging child elements into a single line that can be oriented horizontally or vertically.
Stack panels are useful when you have a menu kind of application / browser kind of application.
The default for both HorizontalAlignment and VerticalAlignment of content in a StackPanel is Stretch.


Grid :

Grid defines a flexible grid area that consists of columns and rows.
Grid enables complex layout.You can define rows and columns inside a grid. By default the grid has one row and one column.
You can position objects in specific cells of the Grid by using the Grid.Column and Grid.Row attached properties.Instead of giving definite sizes to the grid you can specify start sizing/
Star sizing to distributes space proportionally.

Conclusion


Grids are used mostly for almost all kinds of apps.
If you are developing a gaming or a animation app , canvas is the best.
For menus and a hide and show type of controls stack panels are best.

 

Friday, 4 January 2013

Windows 8 : Contact Picker

Suppose you want to create an application which uses mailing , messaging , appointments and social networking.  And you want to access existing contacts rather than adding your own contact, in this case Windows 8 provides you with the Contact Picker API.

Using Contact Picker API you can:
  • Add a contact
  • Pick a contact
  • Pick multiple contacts

Basically the Contact Picker API and ContactPicker class enables apps that to select and acquire info about contacts.

Namespace used is: Windows.ApplicationModel.Contacts

Following are the various classes in this namespace:

Contact
Creates a new contact.
ContactField
Shows a piece of contact data.
ContactFieldFactory
Creates fields that contain information about a contact.
ContactInformation
Contains the information about a contact.
ContactInstantMessageField
Defines a field that is an instant messaging (IM) address.
ContactLocationField
Contains information about a user's location and address.
ContactPicker
Controls how the Contact Picker user interface opens and what information it shows.
KnownContactField
A static class that contains the names of contact fields for storing commonly requested information like email address and phone numbers.

 

In the following example we will use:
  • ContactPicker class
  • ContactInformation class

In this demo I am trying to:
  • Open all the contact information available with me.
  • Select single information.
  • Display the data fetched from the contact information.

The namespaces I added for this sample are:
  • using Windows.ApplicationModel.Contacts;
  • using System.Text;
  • using Windows.Storage.Streams;
  • using Windows.UI.Xaml.Media.Imaging;

In the xaml file , I have six text blocks and one button called ‘pick single contact’

 

When the button is clicked , user is prompted with a screen which lists all the contacts that I have on my Windows 8 device.
I can select a single contact and on clicking the OK button the screen details the contact details of the contact selected in the previous screen.
For the above contact there is no address added, so the address field is empty. If the address fields are present in the contact information the address is also shown.

Now, let us look the xaml code.

<Page
    x:Class="ContactPicker.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:ContactPicker"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d">
 
    <Grid Background="#FFF73131">
        <Image x:Name="OutputThumbnail" Grid.Column="0" Stretch="None" VerticalAlignment="Top" HorizontalAlignment="Left"/>
        <Button Content="Pick Single Contact " HorizontalAlignment="Left" Margin="581,145,0,0" VerticalAlignment="Top" Width="299" Name="PickContact" Click="PickContact_Click" Height="105" FontFamily="Segoe UI Light" FontSize="24" IsDoubleTapEnabled="False">
              <Button.Projection>
                     <PlaneProjection RotationX="-4" RotationY="-6"/>
              </Button.Projection>
        </Button>
        <TextBlock HorizontalAlignment="Left" Margin="704,270,0,0" TextWrapping="Wrap" Text="TextBlock" VerticalAlignment="Top" Height="56" Width="391" Visibility="Collapsed" Name="contactName" RenderTransformOrigin="0.502,5.966" FontFamily="Segoe UI Light" FontSize="32"/>
        <TextBlock HorizontalAlignment="Left" Margin="411.73,271.356,0,0" TextWrapping="Wrap" Text="Contact Name" VerticalAlignment="Top" Height="60.337" Width="247.325" Visibility="Visible" x:Name="contactNameLabel" RenderTransformOrigin="0.502,5.966" FontFamily="Segoe UI Light" FontSize="32" UseLayoutRounding="False" d:LayoutRounding="Auto">
            <TextBlock.RenderTransform>
                <CompositeTransform Rotation="0.166"/>
            </TextBlock.RenderTransform>
        </TextBlock>
        <TextBlock HorizontalAlignment="Left" Margin="413.223,351.953,0,0" TextWrapping="Wrap" Text="Email" VerticalAlignment="Top" Height="60.337" Width="247.325" Visibility="Visible" x:Name="Email" RenderTransformOrigin="0.502,5.966" FontFamily="Segoe UI Light" FontSize="32" UseLayoutRounding="False" d:LayoutRounding="Auto">
            <TextBlock.RenderTransform>
                <CompositeTransform Rotation="0.166"/>
            </TextBlock.RenderTransform>
        </TextBlock>
        <TextBlock HorizontalAlignment="Left" Margin="698,348,0,0" TextWrapping="Wrap" Text="" VerticalAlignment="Top" Height="117" Width="582" Visibility="Visible" x:Name="EmailValue" RenderTransformOrigin="0.502,5.966" FontFamily="Segoe UI Light" FontSize="32"/>
        <TextBlock HorizontalAlignment="Left" Margin="413.223,516.132,0,0" TextWrapping="Wrap" Text="Address" VerticalAlignment="Top" Height="60.337" Width="247.325" Visibility="Visible" x:Name="Address" RenderTransformOrigin="0.502,5.966" FontFamily="Segoe UI Light" FontSize="32" UseLayoutRounding="False" d:LayoutRounding="Auto">
            <TextBlock.RenderTransform>
                <CompositeTransform Rotation="0.166"/>
            </TextBlock.RenderTransform>
        </TextBlock>
        <TextBlock HorizontalAlignment="Left" Margin="682,464,0,0" TextWrapping="Wrap" Text="" VerticalAlignment="Top" Height="241" Width="589" Visibility="Visible" x:Name="AddressValue" RenderTransformOrigin="0.502,5.966" FontFamily="Segoe UI Light" FontSize="32"/>
 
 
    </Grid>
</Page>

 

The xaml code is nothing but a very simple xaml page.

Now , Let us do the button click event:

1.       Create an object of the Contact class

var contactPicker = new Windows.ApplicationModel.Contacts.ContactPicker();

2.       Now , we need to fetch the contact information using the ContactInformation class:

ContactInformation contact = await contactPicker.PickSingleContactAsync();

 

PickSingleContactAsync(); is the method which internally collates all the contact information from my OS and presents to me on the UI.

 

When implementing PickSingleContactAsync();This method has no parameters. Using this method I can select only one contact at a time.

 

Once , I have selected a contact , the contact information is now available , we need to fetch the information and show them in appropriate format.

 

                contactName.Visibility = Visibility.Visible;

                AddressValue.Text = string.Empty;

                contactName.Text = contact.Name;

                EmailValue.Visibility = Visibility.Visible;

                EmailValue.Text = contact.Emails[0].Value.ToString();

                if (contact.Locations.Count > 0)

                {

                    string street = contact.Locations[0].Street.ToString();

                    string city = contact.Locations[0].City.ToString();

                    string category = contact.Locations[0].Category.ToString();

                    string region = contact.Locations[0].Region.ToString();

                    string country = contact.Locations[0].Country.ToString();

 

                    string postalCode = contact.Locations[0].PostalCode.ToString();

                    string address = street + city + region + country + postalCode;

                    AddressValue.Visibility = Visibility.Visible;

                    AddressValue.Text = address;

           }

 

Although , I can get the all the contact information using this, I cannot get the thumbnail information using contact class.

So,  Let us try to fetch the thumbnail information.

To fetch the thumbnail information ,

 IRandomAccessStreamWithContentType stream = await contact.GetThumbnailAsync();

 

And once , you have fetched the image stream use following:

               if (stream != null && stream.Size > 0)

                {

                    BitmapImage bitmap = new BitmapImage();

                    bitmap.SetSource(stream);

                    OutputThumbnail.Source = bitmap;

                }

                else

                {

                    OutputThumbnail.Source = null;

         }

 

So,  the .cs file now looks like:

 

using System;

using System.Collections.Generic;

using System.IO;

using System.Linq;

using Windows.Foundation;

using Windows.Foundation.Collections;

using Windows.UI.Xaml;

using Windows.UI.Xaml.Controls;

using Windows.UI.Xaml.Controls.Primitives;

using Windows.UI.Xaml.Data;

using Windows.UI.Xaml.Input;

using Windows.UI.Xaml.Media;

using Windows.UI.Xaml.Navigation;

using Windows.ApplicationModel.Contacts;

using System.Text;

using Windows.Storage.Streams;

using Windows.UI.Xaml.Media.Imaging;

 

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

 

namespace ContactPicker

{

    /// <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();

        }

 

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

        {

        }

 

     

        private async void PickContact_Click(object sender, RoutedEventArgs e)

        {

            var contactPicker = new Windows.ApplicationModel.Contacts.ContactPicker();

            ContactInformation contact = await contactPicker.PickSingleContactAsync();

            if (contact != null)

            {

                contactName.Visibility = Visibility.Visible;

                AddressValue.Text = string.Empty;

                contactName.Text = contact.Name;

                EmailValue.Visibility = Visibility.Visible;

                EmailValue.Text = contact.Emails[0].Value.ToString();

                if (contact.Locations.Count > 0)

                {

                    string street = contact.Locations[0].Street.ToString();

                    string city = contact.Locations[0].City.ToString();

                    string category = contact.Locations[0].Category.ToString();

                    string region = contact.Locations[0].Region.ToString();

                    string country = contact.Locations[0].Country.ToString();

 

                    string postalCode = contact.Locations[0].PostalCode.ToString();

                    string address = street + city + region + country + postalCode;

                    AddressValue.Visibility = Visibility.Visible;

                    AddressValue.Text = address;

                }

 

                IRandomAccessStreamWithContentType stream = await contact.GetThumbnailAsync();

                if (stream != null && stream.Size > 0)

                {

                    BitmapImage bitmap = new BitmapImage();

                    bitmap.SetSource(stream);

                    OutputThumbnail.Source = bitmap;

                }

                else

                {

                    OutputThumbnail.Source = null;

                }

 

            }

       }

           

    }

 

  

  

}