Follow @PDSAInc October 2010 - Posts - Paul Sheriff's Blog for the Real World

Paul Sheriff's Blog for the Real World

This blog is to share my tips and tricks garnered over 25+ years in the IT industry

Paul's Favorites

October 2010 - Posts

Windows Phone List Box with Images

Developing for Windows Phone is easy if you have been doing any XAML at all. That’s because you use Silverlight for Windows Phone development! This is a great thing because everything you already know you can apply immediately. Let’s take a simple example like presenting a list of products with images in a list box (Figure 1) in the Windows Phone emulator. This article assumes that you have VS.NET 2010 and the Windows Phone tools installed along with it. The Windows Phone tools must be downloaded separately and installed with VS.NET 2010. You may also download the free VS.NET 2010 Express for Windows Phone developer environment.

Figure 1: Windows Phone List Box With Images

Figure 1: Windows Phone List Box With Images

The Product Class
For this example, I will be using a Product class with three properties, and a collection class of Product objects using the Generic List class.

You can create this sample by creating a Product class as shown in the following code:

public class Product {

  public Product() { }

  public Product(string name, decimal price, string imageUri)
  {
    this.ProductName = name;
    this.Price = price;
    this.ImageUri = imageUri;
  }

  public string ProductName { get; set; }
  public decimal Price { get; set; }
  public string ImageUri { get; set; }
}

Create a collection class that initializes a property called DataCollection with some sample data as shown in the code below:

public class Products : List<Product> {
  public Products() {
    BuildCollection();
  }

  public List<Product> DataCollection { get; set; }

  List<Product> BuildCollection() {
    DataCollection = new List<Product>();

    DataCollection.Add(new Product(
      "Haystack Code Generator for .NET", 799, "Haystack.jpg”));
    DataCollection.Add(new Product(
      "Fundamentals of N-Tier eBook", 19.95, "NTier.jpg"));

    // MORE PRODUCTS HERE – REMOVED FOR BREVITY

    return DataCollection;
  }
}

Value Converter

As you can see in Figure 1, the Price is shown in a currency format. Unfortunately in the Windows Phone version of Silverlight, the StringFormat attribute on the Binding class is absent. So you will need to create a value converter for displaying a value in a currency format. Create the following class that implements the IValueConverter interface. In the Convert method you will then take the “value” parameter passed in, convert it to a decimal value, then return that value as a string formatted with the ”c” option in the ToString() method.

public class PriceConverter : IValueConverter
{
  public object Convert(object value, Type targetType,
     object parameter, System.Globalization.CultureInfo culture)
  {
    decimal price;

    price = (decimal)value;

    return price.ToString("c");
  }

  public object ConvertBack(object value, Type targetType,
    object parameter, System.Globalization.CultureInfo culture)
  {
    throw new NotImplementedException();
  }
}

Create Classes in XAML

Now that you have the Product class, the Products class and the PriceConverter classes created, you now need to create an instance of the Products collection class and the PriceConverter class in your XAML. In your MainPage.xaml, add an xml namespace to the name of your project as shown here:

xmlns:data="clr-namespace:WPListBoxImage"

Next you create an instance of the Products and PriceConverter class in XAML. The constructor for the Products class will create the initial collection of product objects.

<phone:PhoneApplicationPage.Resources>
  <data:Products x:Key="productCollection" />
  <data:PriceConverter x:Key="priceConvert" />
</phone:PhoneApplicationPage.Resources>

These two classes may now be used within the rest of your XAML by referencing them by their Key name.

Create List Box

Now it is time to create the List Box and connect it to the static resource you created in the above XAML. Below is the XAML used for the complete list box. After you look at this XAML you will learn about each of the various pieces that make up the list box.

<ListBox x:Name="lstData"
     ItemsSource="{Binding
                    Source={StaticResource productCollection},
                    Path=DataCollection}">
  <ListBox.ItemTemplate>
    <DataTemplate>
      <StackPanel Orientation="Horizontal">
        <Image Margin="8"
                VerticalAlignment="Top"
                Source="{Binding Path=ImageUri}"
                Width="100"
                Height="100" />
        <StackPanel>
          <TextBlock Margin="8" Width="250"
                      TextWrapping="Wrap"
                      VerticalAlignment="Top"
                      HorizontalAlignment="Left"
                      Text="{Binding Path=ProductName}" />
          <TextBlock Width="100"
                      Margin="8,0,8,8"
                      VerticalAlignment="Top"
                      HorizontalAlignment="Left"
                      Text="{Binding Path=Price,
                      Converter={StaticResource priceConvert}}" />
        </StackPanel>
      </StackPanel>
    </DataTemplate>
  </ListBox.ItemTemplate>
</ListBox>

Let’s now break down each of the areas of the ListBox XAML shown above. First, notice the ItemsSource property is simply setup to reference the static resource you created named “productCollection”. This is the Products collection class. The Path attribute refers to the DataCollection property within the Products collection that was created in the constructor of the Products class.

<ListBox x:Name="lstData"
         ItemsSource="{Binding
                 Source={StaticResource productCollection},
                 Path=DataCollection}">

Next, you have the definition for each row in the list box defined in the ItemsTemplate. The ItemsTemplate should not be to foreign to anyone that has done XAML. Each row of the ListBox is defined within the <DataTemplate> area of the ItemsTemplate. In this XAML you will have a <StackPanel> control with its orientation set to “Horizontal”. This is done so the Image can be on the left side and the text for the product name and the price can be on the right side of the row.

Notice in the text block that displays the actual price the use of the value converter class you created earlier. You bind to the Price property using the Path attribute of the Binding class. However, before the Binding class displays the Price it passes it through the converter. The Convert() method of the PriceConverter class formats the price and returns it as a string to be displayed in the TextBlock.

Summary

That’s all there is to creating a list box that displays some product data in a Windows Phone application. Again, there is not a lot different here as you will just be using Silverlight to develop for the Windows Phone. Of course, there are some considerations you need to think about when developing for the phone. First you need to think about the font size and the spacing between items in a list box. If you are going to have your user select one of your entries, you want to leave plenty of space for their fingers to select the item they want, and not hit one of the surrounding items by mistake. So, download the Windows Phone tools for VS.NET 2010 and start developing phone apps!

NOTE: You can download the complete sample code (in both VB and C#) at my website. http://www.pdsa.com/downloads. Choose Tips & Tricks, then "Windows Phone Image List Box" from the drop-down.

Good Luck with your Coding,
Paul Sheriff

** SPECIAL OFFER FOR MY BLOG READERS **
Visit http://www.pdsa.com/Event/Blog for a free videos on Silverlight entitled Silverlight XAML for the Complete Novice - Part 1.

Horizontal List Boxes in Silverlight

A list box in XAML does not just have to look like a normal list box with just a single line of data in each row. You can place multiple rows into the list box, and you can even turn the list box so it displays the data horizontally instead of vertically (see Figure 1).

Horizontal ListBox
Figure 1: A List Box can display its data horizontally

The Product Class

For this example, I will be using a simple Product class with three properties, and a collection class of Product objects using the Generic List class. You can create this sample by creating a Product class as shown in the following code:

public class Product {
  public Product() { }

  public Product(string name, string type, decimal price)
  {
    this.ProductName = name;
    this.ProductType = type;
    this.Price = price;
  }

  public string ProductName { get; set; }
  public string ProductType { get; set; }
  public decimal Price { get; set; }
}

Create a collection class that initializes a property called DataCollection with some sample data as shown in the code below:

public class Products : List<Product> {
  public Products() {
    BuildCollection();
  }

  public List<Product> DataCollection { get; set; }

  List<Product> BuildCollection() {
    DataCollection = new List<Product>();

    DataCollection.Add(new Product(
      "Haystack Code Generator for .NET", "Product", 799));
    DataCollection.Add(new Product(
      "Fundamentals of N-Tier eBook", "Book", 19.95));

    // MORE PRODUCTS HERE – REMOVED FOR BREVITY

    return DataCollection;
  }
}

Create Instance of Product Class in XAML

The first thing you need to do is to create an instance of the Products collection class in your XAML. In your MainPage.xaml, add an xml namespace to the name of your project as shown here:

xmlns:data="clr-namespace:SLHorizontal "

Next you create an instance of the Products class in XAML. The constructor for the Products class will create the initial collection of product objects.

<UserControl.Resources>
  <data:Products x:Key="productCollection" />
</UserControl.Resources>

Create Horizontal List Box

Now it is time to create the List Box and connect it to the static resource you created in the above XAML. Below is the XAML used for the complete list box. After you look at this XAML you will learn about each of the various pieces that make up the horizontal list box.

<ListBox Height="200"
          Name="lstData"
          Background="Beige"
          ItemsSource="{Binding
                  Source={StaticResource productCollection},
                  Path=DataCollection}">
  <ListBox.ItemsPanel>
    <ItemsPanelTemplate>
      <StackPanel Orientation="Horizontal" />
    </ItemsPanelTemplate>
  </ListBox.ItemsPanel>
  <ListBox.ItemTemplate>
    <DataTemplate>
      <Border BorderBrush="Gray"
              Margin="6,2,6,2"
              Padding="4"
              BorderThickness="2"
              CornerRadius="5"
              Background="Aqua"
              Width="250">
        <StackPanel Orientation="Vertical"
                    HorizontalAlignment="Left"
                    Margin="8">
          <TextBlock FontSize="16"
                      TextWrapping="Wrap"
                      Text="{Binding Path=ProductName}" />
          <StackPanel Orientation="Horizontal">
            <TextBlock FontSize="12"
                        Text="Type: " />
            <TextBlock FontSize="12"
                        Text="{Binding Path=ProductType}" />
            <TextBlock FontSize="12"
                        Margin="10,0,0,0"
                        Text="Price: " />
            <TextBlock FontSize="12"
                        Text="{Binding Path=Price,
                                      StringFormat=c}" />
          </StackPanel>
        </StackPanel>
      </Border>
    </DataTemplate>
  </ListBox.ItemTemplate>
</ListBox>

Let’s now break down each of the areas of the ListBox XAML shown above. First, notice the ItemsSource property is simply setup to reference the static resource you created named “productCollection”. This is the Products collection class. The Path attribute refers to the DataCollection property within the Products collection that was created in the constructor of the Products class.

<ListBox Height="200"
          Name="lstData"
          Background="Beige"
          ItemsSource="{Binding
                  Source={StaticResource productCollection},
                  Path=DataCollection}">

Next, and probably the most important part of the XAML is the ItemsPanel element. While you may have used the ItemsTemplate element before to create the layout of each row in the list, the ItemsPanel is used to control the overall look of the list box itself, not each individual item. When Microsoft defined the default look for the list box, they used a normal StackPanel control which has its Orientation set to vertical. However, we want our list box to be display horizontally so you simply need to set the ItemsPanelTemplate with a StackPanel that has its Orientation attribute set to Horizontal. This is what makes the list box display each row horizontally.

<ListBox.ItemsPanel>
  <ItemsPanelTemplate>
    <StackPanel Orientation="Horizontal" />
  </ItemsPanelTemplate>
</ListBox.ItemsPanel>

Finally you have the definition for each “row” in the list box defined in the ItemsTemplate. Each row is encased in a <Border> control to give each row a separate and distinct look with a rounded border and an aqua blue background. Next, there is a <StackPanel> control to display the data vertically. The product name is displayed in a TextBlock with text wrapping turned on. Next there is another <StackPanel> control with its orientation set to horizontal to display the product type and price of each product side by side.

<Border BorderBrush="Gray"
        Margin="6,2,6,2"
        Padding="4"
        BorderThickness="2"
        CornerRadius="5"
        Background="Aqua"
        Width="250">
  <StackPanel Orientation="Vertical"
              HorizontalAlignment="Left"
              Margin="8">
    <TextBlock FontSize="16"
               TextWrapping="Wrap"
               Text="{Binding Path=ProductName}" />
    <StackPanel Orientation="Horizontal">
      <TextBlock FontSize="12"
                 Text="Type: " />
      <TextBlock FontSize="12"
                 Text="{Binding Path=ProductType}" />
      <TextBlock FontSize="12"
                 Margin="10,0,0,0"
                 Text="Price: " />
      <TextBlock FontSize="12"
                 Text="{Binding Path=Price,
                                StringFormat=c}" />
    </StackPanel>
  </StackPanel>
</Border>

Notice in the text block that displays the actual price the use of the StringFormat attribute to display the decimal value for the price in a currency format. This is accomplished using “c” for the value passed to StringFormat.

Summary

In this blog entry you learned how to create a list box that displays data horizontally instead of vertically. The ListBox control in Silverlight is very flexible and you are really only limited by your imagination. We have used the ListBox for simulating Tab controls, for menu systems, and we have even used a ListBox as each row within another list box.

NOTE: You can download the complete sample code (in both VB and C#) at my website. http://www.pdsa.com/downloads. Choose Tips & Tricks, then "Horizontal List Box in Silverlight" from the drop-down.

Good Luck with your Coding,
Paul Sheriff

** SPECIAL OFFER FOR MY BLOG READERS **
Visit http://www.pdsa.com/Event/Blog for a free videos on Silverlight entitled Silverlight XAML for the Complete Novice - Part 1.

 

More Posts