Displaying the Product List

,

The list of products exposed by the ProductsViewModel.Products property is displayed using a ListBox control in the ProductsView page. The ListBox’s ItemTemplate has various controls that are used to display the details of each Product, as shown in the following excerpt:

<StackPanel Grid.Row="1" Margin="10"
            Visibility="{Binding Loaded,
                Converter={StaticResource BooleanToVisibilityConverter},
                ConverterParameter=Visible}">
    <ScrollViewer>
        <ListBox ItemsSource="{Binding Products}" Height="610">
            <ListBox.ItemTemplate>
                <DataTemplate>
                    <StackPanel Orientation="Horizontal">
                        <Image Source="{Binding SmallImageUri}"
                               MaxWidth="150" MaxHeight="150"
                               Margin="0,0,10,10" />
                        <StackPanel Margin="5">
                            <TextBlock Text="{Binding Title}"
                                       TextWrapping="Wrap" />
                            <TextBlock Text="{Binding Price,
                                                StringFormat={0:C}}" />
                            <HyperlinkButton
                                NavigateUri="{Binding Id,
                                    StringFormat=/ProductDetails/{0}}"
                                Content="View Details"
                                HorizontalAlignment="Left" Margin="0,10,0,0" />
                        </StackPanel>
                    </StackPanel>
                </DataTemplate>
            </ListBox.ItemTemplate>
        </ListBox>
    </ScrollViewer>
</StackPanel>

An Image control displays a thumbnail of the product, using the SmallImageUri property of the Product.

A string format is used to convert the Price property, which is a double value, to a currency formatted string using the format {0:C}. Similarly, a link is provided for the product details page, using the format /ProductDetails/{0}, and the value of the Product’s Id is substituted for the {0} placeholder. The UriMapping for this product details URI causes the application to reroute to the full URI of the ProductDetailsView.xaml page and includes the productId query string parameter.

Figure 3.11 shows the ProductsView displaying a list of books.

Image

FIGURE 3.11 Products View.

When the user presses the HyperlinkButton, he is directed to the ProductDetailsView.xaml page. This page displays the various properties of the product and includes a link for an external website, where the user can find more information about the product (see Figure 3.12).

Image

FIGURE 3.12 View a product’s details.

When navigating to the ProductDetailsView the page attempts to retrieve the productId query string parameter from the NavigationContext (see Listing 3.10).

LISTING 3.10. ProductDetailsView Class (excerpt)


public partial class ProductDetailsView : PhoneApplicationPage
{
    public ProductDetailsView()
    {
        InitializeComponent();

        DataContext = new ProductDetailsViewModel(
            PhoneApplicationService.Current.State);    }
    ProductDetailsViewModel ViewModel
    {
        get
        {
            return (ProductDetailsViewModel)DataContext;
        }
    }

    protected override void OnNavigatedTo(NavigationEventArgs e)
    {        base.OnNavigatedTo(e);
        string productIdString = NavigationContext.QueryString["productId"];
        int productId = int.Parse(productIdString);
        ViewModel.LoadProduct(productId);
    }

    protected override void OnNavigatedFrom(NavigationEventArgs e)
    {        ViewModel.SaveTransientState();
        base.OnNavigatedFrom(e);
    }
}


The view then passes the parameter along to the ProductDetailsViewModel class, which handles the loading of the specified product (see Listing 3.11). The LoadProduct method first tests for the existence of the product in transient state. If not present, it retrieves the product using the service client.

LISTING 3.11. ProductDetailsViewModel Class (excerpt)


public class ProductDetailsViewModel : ViewModelBase
{
    const string transientStateKey = "ProductDetailsViewModel_Product";
    readonly IDictionary<string, object> transientStateDictionary;
    public ProductDetailsViewModel(
        IDictionary<string, object> transientStateDictionary)
    {
        this.transientStateDictionary = ArgumentValidator.AssertNotNull(
            transientStateDictionary, "transientStateDictionary");
    }

    public void LoadProduct(int productId)
    {
        object transientState;
        if (PhoneApplicationService.Current.State.TryGetValue(
                transientStateKey, out transientState))
        {
            product = transientState as Product;
            if (product != null && product.Id == productId)
            {
                return;
            }
        }

        BookshopServiceClient client = new BookshopServiceClient();
        client.GetProductByIdCompleted += (sender, args) =>
        {
            if (args.Error != null)
            {
                throw args.Error;
            }
            Product = args.Result;
        };
        client.GetProductByIdAsync(productId);
    }
    Product product;

    public Product Product
    {
        get
        {
            return product;
        }
        /* Setter is not private to enable sample data.
         * See ProductDetailsViewSampleData.xaml */
        internal set
        {
            product = value;
            OnPropertyChanged("Product");
        }
    }

    public void SaveTransientState()
    {        transientStateDictionary[transientStateKey] = product;
    }
}


When navigating away from the page, the viewmodel’s SaveTransientState method is called, which places the product in the state dictionary.

The ProductDetailsView.xaml page presents the product details via the viewmodel’s Product property (see Listing 3.12).

LISTING 3.12. ProductDetailsView.xaml (excerpt)


<StackPanel Grid.Row="1"
    Style="{StaticResource PageContentPanelStyle}"
    d:DataContext="{d:DesignData Source=ProductDetailsViewSampleData.xaml}">

    <TextBlock Text="{Binding Product.Title}" TextWrapping="Wrap"
               Style="{StaticResource PhoneTextTitle2Style}"/>
    <StackPanel Orientation="Horizontal">
        <Image Source="{Binding Product.LargeImageUri,
                Converter={StaticResource ImageCacheConverter}}"
                MaxWidth="250" MaxHeight="250" Margin="10,10,0,10" />
        <StackPanel>
            <TextBlock Text="{Binding Product.Author}" TextWrapping="Wrap"
                       Style="{StaticResource PhoneTextTitle3Style}"/>
            <TextBlock Text="{Binding Product.Price, StringFormat={0:C}}"
                       Style="{StaticResource PhoneTextTitle3Style}"/>
            <StackPanel Orientation="Horizontal">
                <TextBlock Text="ISBN"
                           Style="{StaticResource PhoneTextTitle3Style}" />
                <TextBlock Text="{Binding Product.Isbn13}"
                           TextWrapping="Wrap"
                           Style="{StaticResource PhoneTextNormalStyle}" />
            </StackPanel>

            <HyperlinkButton
                NavigateUri="{Binding Product.ExternalUrl,
                               StringFormat=/WebBrowser/{0}}"
                Content="External Page"
               Margin="0,10,0,0" HorizontalAlignment="Left" />
        </StackPanel>
    </StackPanel>
    <TextBlock Text="{Binding Product.Description}"
               Margin="10,20,0,10" TextWrapping="Wrap" />
</StackPanel>


The StackPanel includes a d:DataContext attribute that defines a design-time data context object, discussed in the next section.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.12.73.64