Intersoft ClientUI Documentation
Walkthrough: Display Item Details in UXFrame using MVVM Pattern

This walkthrough shows you how to use a UXFrame to list and show item detail with MVVM pattern. This walkthrough demonstrates the following concept:

Prerequisites

You need the following components to complete this walkthrough:

In addition, you need the following resources to complete this walkthrough:

The assembly is required for the XML data source and images

Creating a New Intersoft ClientUI MVVM Application Project

The first step is to create a new ClientUI MVVM Application project using Intersoft ClientUI MVVM Application project template in Visual Studio.

To create the ClientUI MVVM Application project

  1. Start Visual Studio 2010.
  2. Create a new ClientUI MVVM Application project using Intersoft ClientUI MVVM Application project template. To learn more, see Walkthrough: Create New Intersoft ClientUI MVVM Application Template.
  3. In project reference, add System.Xml.Linq.dll. This assembly is required to perform LINQ query to xml data.
  4. Also add reference to Intersoft.ClientUI.Samples.Assets assembly, the assembly is available from the provided ClientUI sample. 

Creating the Model Class

This section shows how to create a Book model class in Book.cs. The model will map each information in the data entity to a property.

To create the Book model class

  1. Create a new Book.cs under the Models folder and inherit the ModelBase class.
  2. Create a private variable and a public property for Author node with a String data type. In the setter property, OnPropertyChanged method must be called after the property is assigned a new value.
    C#
    Copy Code
    private string _author;
    
    public string Author
    {
        get
        {
            return _author;
        }
        set
        {
            if (_author != value)
            {
                _author = value;
                OnPropertyChanged("Author");
            }
        }
    }
  3. Repeat the process for ID, Title, Category, Price, and Image node. String data type is used for ID, Title, and Category. Double is used for Price. Uri is used for Image.
  4. Create a string property to return a Uri with Book ID to be used in the later steps for navigation purpose.
    C#
    Copy Code
    public Uri NavigateUri
    {
        get { return new Uri("/Books/" + this.ID, UriKind.RelativeOrAbsolute); }
    }
  5. Create a constructor which accept XElement parameter which will be mapped to each property in the class.
    C#
    Copy Code
    public Book(XElement x)
        : this()
    {
        this._author = x.Element("Author").Value.Trim();
        this._title = x.Element("Title").Value.Trim();
        this._category = x.Element("Category").Value.Trim();
        this._ID = x.Element("ID").Value.Trim();
        this._price = double.Parse(x.Element("Price").Value.Trim());
        this._image = new Uri("/Intersoft.ClientUI.Samples.Assets;component/Images/Books/" + x.Element("Image").Value.Trim(), UriKind.RelativeOrAbsolute);
    }

Creating the ViewModel

This section shows how to create a ViewModel to hold the collection of Book model object.

  1. Create a new BookListViewModel.cs under the ViewModels folder and inherit the ViewModelBase class.
  2. Create a public property to hold the collection of Book object.
    C#
    Copy Code
    public ObservableCollection<Book> FilteredBooks{ get; set; }
  3. Create a LoadBooks method which will be called in the constructor to load the Book object from the XML file to the Book collection variable. In this scenario only books with specific category is loaded.
    C#
    Copy Code
    public BookListViewModel()
    {
        this.LoadBooks();
    }
    
    private void LoadBooks()
    {
        // loads book data from xml file
        StreamResourceInfo resource = System.Windows.Application.GetResourceStream(
                new Uri("Intersoft.ClientUI.Samples.Assets;component/Data/BookDataSource.xml", UriKind.Relative));
    
        XDocument doc = XDocument.Load(resource.Stream);
    
        var filteredBooks = (from x in doc.Descendants("Book")
                                where x.Element("Category").Value.Trim() == "Computing and Internet"
                                select new Book(x)).Take(8);
    
        FilteredBooks = new ObservableCollection<Book>(filteredBooks);
    }

Creating the View

This section shows how to create three pages used for navigation purpose. The BookList.xaml is used to list all the Book object collection while the BookDetail.xaml is used to display detail information of a specific book. The BookContainer.xaml is used to navigate between the BookList and BookDetail view.

To create the BookList view

This section shows how to create a page which will list the Book collection in a WrapPanel, the page is using the BookList.xaml.

  1. Add a new UXPage to the Views folder in your Silverlight project and name it BookList.xaml.
    For more information on how to add a new item in Visual Studio, see Walkthrough: Add New Item such as Page, Dialog Box and Window in VS 2010
  2. Declare the namespace that maps to the BookListViewModel class.
    XAML
    Copy Code
    xmlns:ViewModels="clr-namespace:ItemDetailUXFrame.ViewModels"
  3. Reference the BookListViewModel as the page DataContext.
    XAML
    Copy Code
    <Intersoft:UXPage.DataContext>
        <ViewModels:BookListViewModel/>
    </Intersoft:UXPage.DataContext>
  4. Add UXItemsControl and set the HorizontalAligment property and VerticalAlignment property to Stretch. In addition, set the following property:
    Locate the ItemsSource property.
    1. Click the ellipsis button in the header property column, a context menu will appear
    2. Select the Apply DataBinding Options...
    3. From the Tab Path, select FilteredBooks
  5. Set the UXItemsControl ItemPanel to use WrapPanel with Horizontal Orientation.
    XAML
    Copy Code
    <Intersoft:UXItemsControl ...>
        <Intersoft:UXItemsControl.ItemsPanel>
            <ItemsPanelTemplate>
                <Intersoft:WrapPanel Orientation="Horizontal"/>
            </ItemsPanelTemplate>                
        </Intersoft:UXItemsControl.ItemsPanel>
    </Intersoft:UXItemsControl>
  6. Set the UXItemsControl ItemTemplate to use UXHyperlinkButton. Set the following properties in the UXHyperlinkButton:
    Property Value
    Padding 0
    ToolTipService.ToolTip {Binding Title}
    NavigateUri {Binding NavigateUri}
    TargetName Frame1
    Frame1 will be the name of the UXFrame on the main page
  7. Add a new Image control under the UXHyperlinkButton and set Source property to {Binding Image} and Width property to 76.
    XAML
    Copy Code
    <Intersoft:UXItemsControl ...>
        ...
        <Intersoft:UXItemsControl.ItemTemplate>
            <DataTemplate>
                <Intersoft:UXHyperlinkButton Padding="0" ToolTipService.ToolTip="{Binding Title}"
                                                NavigateUri="{Binding NavigateUri}" TargetName="Frame1">
                    <Image Source="{Binding Image}" Width="76"/>
                </Intersoft:UXHyperlinkButton>
            </DataTemplate>
        </Intersoft:UXItemsControl.ItemTemplate>
    </Intersoft:UXItemsControl>

To create the BookDetail view

This section shows how to create a page which details the selected Book, the page is using the BookDetail.xaml.

  1. Add a new UXPage to the Views folder in your Silverlight project and name it BookDetail.xaml.
    For more information on how to add a new item in Visual Studio, see Walkthrough: Add New Item such as Page, Dialog Box and Window in VS 2010
  2. Declare the namespace that maps to the Book model class.
    XAML
    Copy Code
    xmlns:Model="clr-namespace:ItemDetailUXFrame.Models"
  3. Reference the Book as the page DataContext. This step is done to easily bind data to the control in designer view.
    XAML
    Copy Code
    <Intersoft:UXPage.DataContext>
        <Model:Book />
    </Intersoft:UXPage.DataContext>
  4. Add a DockPanel. Set the HorizontalAlignment property and VerticalAlignment property to Stretch.
  5. Add a TextBlock in the DockPanel, set the Intersoft:DockPanel.Dock property to Top, TextWrapping property to Wrap, and HorizontalAlignment property to Left. In addition, set the following property:
    Locate the Text property.
    1. Click the ellipsis button in the header property column, a context menu will appear
    2. Select the Apply DataBinding Options...
    3. From the Tab Path, select Title
  6. Add an Image control in the DockPanel, set the Intersoft:DockPanel.Dock property to Left. In addition, set the following properties:
    Locate the Source property.
    1. Click the ellipsis button in the header property column, a context menu will appear
    2. Select the Apply DataBinding Options...
    3. From the Tab Path, select Image
  7. Add a StackPanel in the DockPanel, set the Intersoft:DockPanel.IsFillElement property to True and Orientation property to Vertical.
  8. Add four FieldLabel in the StackPanel. Set the following properties:
    Property Value
    HeaderWidth 70
    Header ID:
      Price:
      Author:
      Category:
  9. Set each content of the FieldLabel to use TextBlock. Set the following properties for the TextBlock:
    VerticalAlignment: Center
    Locate the Text property.
    1. Click the ellipsis button in the header property column, a context menu will appear
    2. Select the Apply DataBinding Options...
    3. From the Tab Path, select ID
    Do the same steps to bind Price, Author, and Category
  10. On the OnNavigatedTo method set the page DataContext to the Book referenced by the page query string ID.
    Sample Code
    Copy Code
    protected override void OnNavigatedTo(NavigationEventArgs e)
    {
        if (this.NavigationContextExtended.QueryString.Count > 0)
        {
            string id = this.NavigationContextExtended.QueryString["ID"];
    
            if (!string.IsNullOrEmpty(id))
            {
                BookListViewModel books = new BookListViewModel();
                this.DataContext = books.FilteredBooks.SingleOrDefault(book => book.ID == id);
            }
        }
    }

To create the BookContainer view

This section shows how to create the main page which hosts the UXFrame and a UXJournalButtons, the page is using BookContainer.xaml.

  1. Add a new UXPage to the Views folder in your Silverlight project and name it BookContainer.xaml.
    For more information on how to add a new item in Visual Studio, see Walkthrough: Add New Item such as Page, Dialog Box and Window in VS 2010
  2. Add a new UXFrame control. Set the following properties:
    Property Value
    Name Frame1
    HorizontalAlignment Stretch
    VerticalAlignment Stretch
    Margin 10,24,10,10
    UseGlobalShell True
    Source /BookList
    /BookList is a URI name set in the next step which refers to the BookList view.
  3. Add a UXFrame UriMapper for the item list and item detail page.
    Sample Code
    Copy Code
    <Intersoft:UXFrame.UriMapper>
        <Intersoft:UriMapper>
            <Intersoft:UriMapping Uri="/BookList" MappedUri="/ItemDetailUXFrame;ItemDetailUXFrame.Views.BookList"/>
            <Intersoft:UriMapping Uri="/Books/{ID}" MappedUri="/ItemDetailUXFrame;ItemDetailUXFrame.Views.BookDetail?ID={ID}"/>
        </Intersoft:UriMapper>
    </Intersoft:UXFrame.UriMapper>
  4. Add a new UXJournalButtons control. Set the following properties:
    Property Value
    VerticalAlignment Top
    HorizontalAlignment Left
    ForwardButtonVisibility Collapsed
    Height 24
    Margin 24
    Height 10,0,0,0
    Locate the NavigationTarget property.
    1. Click the ellipsis button in the header property column, a context menu will appear
    2. Select the Apply DataBinding Options...
    3. From the Source Path, select ElementName > Frame1

Viewing The Result

In order to view the result, you will need to build the Silverlight project and run the test page aspx on a browser.

To view the result

  1. By default, the page display BookList page.
  2. Clicking one of the Book Image navigate the UXFrame to BookDetail page.
  3. Clicking the UXJournalButtons shows the BookList page.

Conclusion

In this walkthrough, you have learned how to create ClientUI MVVM Application project using Intersoft ClientUI MVVM Application project template, and create classes and page based on the MVVM pattern. You also learned how to utilize navigation feature using UXHyperlinkButton and UXJournalButtons in UXFrame.

For more information about application development using MVVM pattern, see MVVM Pattern Overview. For more information about navigation framework and its concepts, see Navigation Overview.

Complete Code Listing

This section lists the complete code used in this walkthrough.

BookListViewModel.cs

Source Code
Copy Code
using System.Collections.ObjectModel;
using System.Linq;
using ItemDetailUXFrame.Models;
using System.Windows.Resources;
using System;
using System.Xml.Linq;

namespace ItemDetailUXFrame.ViewModels
{
    public class BookListViewModel : ViewModelBase
    {
        public ObservableCollection<Book> FilteredBooks { get; set; }

        public BookListViewModel()
        {
            this.LoadBooks();
        }

        private void LoadBooks()
        {
            // loads book data from xml file
            StreamResourceInfo resource = System.Windows.Application.GetResourceStream(
                    new Uri("Intersoft.ClientUI.Samples.Assets;component/Data/BookDataSource.xml", UriKind.Relative));

            XDocument doc = XDocument.Load(resource.Stream);

            var filteredBooks = (from x in doc.Descendants("Book")
                                 where x.Element("Category").Value.Trim() == "Computing and Internet"
                                 select new Book(x)).Take(8);

            FilteredBooks = new ObservableCollection<Book>(filteredBooks);
        }
    }
}

Book.cs

Source Code
Copy Code
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;
using ItemDetailUXFrame.ViewModels;
using System.Xml.Linq;

namespace ItemDetailUXFrame.Models
{
    public class Book : ModelBase
    {
        public Book()
        {
        }

        public Book(XElement x)
            : this()
        {
            this._author = x.Element("Author").Value.Trim();
            this._title = x.Element("Title").Value.Trim();
            this._category = x.Element("Category").Value.Trim();
            this._ID = x.Element("ID").Value.Trim();
            this._price = double.Parse(x.Element("Price").Value.Trim());
            this._image = new Uri("/Intersoft.ClientUI.Samples.Assets;component/Images/Books/" + x.Element("Image").Value.Trim(), UriKind.RelativeOrAbsolute);
        }

        private Uri _image = null;
        private string _author;
        private string _title;
        private string _category;
        private string _ID;
        private double _price;

        public string Author
        {
            get
            {
                return _author;
            }
            set
            {
                if (_author != value)
                {
                    _author = value;
                    OnPropertyChanged("Author");
                }
            }
        }

        public string Title
        {
            get
            {
                return _title;
            }
            set
            {
                if (_title != value)
                {
                    _title = value;
                    OnPropertyChanged("Title");
                }
            }
        }

        public string Category
        {
            get
            {
                return _category;
            }
            set
            {
                if (_category != value)
                {
                    _category = value;
                    OnPropertyChanged("Category");
                }
            }
        }

        public string ID
        {
            get
            {
                return _ID;
            }
            set
            {
                if (_ID != value)
                {
                    _ID = value;
                    OnPropertyChanged("ID");
                }
            }
        }

        public double Price
        {
            get
            {
                return _price;
            }
            set
            {
                if (_price != value)
                {
                    _price = value;
                    OnPropertyChanged("Price");
                }
            }
        }

        public Uri Image
        {
            get
            {
                return _image;
            }
            set
            {
                if (_image != value)
                {
                    _image = value;
                    OnPropertyChanged("Image");
                }
            }
        }

        public Uri NavigateUri
        {
            get { return new Uri("/Books/" + this.ID, UriKind.RelativeOrAbsolute); }
        }
    }
}

BookList.xaml

Sample Code
Copy Code
<Intersoft:UXPage 
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:ViewModels="clr-namespace:ItemDetailUXFrame.ViewModels"
        mc:Ignorable="d"
        xmlns:Intersoft="http://intersoft.clientui.com/schemas"
        x:Class="ItemDetailUXFrame.Views.BookList" 
        Title="BookList Page"
        d:DesignWidth="640" d:DesignHeight="480">
<Intersoft:UXPage.DataContext>
    <ViewModels:BookListViewModel/>
</Intersoft:UXPage.DataContext>
    <Grid x:Name="LayoutRoot">
        <Intersoft:UXItemsControl HorizontalAlignment="Stretch" Name="uXItemsControl1" VerticalAlignment="Stretch" ItemsSource="{Binding Path=FilteredBooks}">
            <Intersoft:UXItemsControl.ItemsPanel>
                <ItemsPanelTemplate>
                    <Intersoft:WrapPanel Orientation="Horizontal"/>
                </ItemsPanelTemplate>                
            </Intersoft:UXItemsControl.ItemsPanel>
            <Intersoft:UXItemsControl.ItemTemplate>
                <DataTemplate>
                    <Intersoft:UXHyperlinkButton Padding="0" ToolTipService.ToolTip="{Binding Title}"
                                                 NavigateUri="{Binding NavigateUri}" TargetName="Frame1">
                        <Image Source="{Binding Image}" Width="76"/>
                    </Intersoft:UXHyperlinkButton>
                </DataTemplate>
            </Intersoft:UXItemsControl.ItemTemplate>
        </Intersoft:UXItemsControl>
    </Grid>
</Intersoft:UXPage>

BookDetail.xaml

Sample Code
Copy Code
<Intersoft:UXPage 
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:Model="clr-namespace:ItemDetailUXFrame.Models"
        mc:Ignorable="d"
        xmlns:Intersoft="http://intersoft.clientui.com/schemas"
        x:Class="ItemDetailUXFrame.Views.BookDetail" 
        Title="BookDetail Page"
        d:DesignWidth="640" d:DesignHeight="480">
    <Intersoft:UXPage.DataContext>
        <Model:Book />
    </Intersoft:UXPage.DataContext>
    <Grid x:Name="LayoutRoot">
        <Intersoft:DockPanel HorizontalAlignment="Stretch" Name="dockPanel1" VerticalAlignment="Stretch" FillChildMode="Custom">
            <TextBlock Name="textBlock1" Intersoft:DockPanel.Dock="Top" TextWrapping="Wrap" HorizontalAlignment="Left" Text="{Binding Path=Title}" />
            <Image Name="image1" Stretch="None" Intersoft:DockPanel.Dock="Left" Width="220" Source="{Binding Path=Image}" VerticalAlignment="Top" />
            <Intersoft:UXStackPanel Name="uXStackPanel1" Intersoft:DockPanel.Dock="Right" Intersoft:DockPanel.IsFillElement="True" Orientation="Vertical">
                <Intersoft:FieldLabel Header="ID: " Name="fieldLabel1" HeaderWidth="70">
                    <TextBlock Name="textBlock2" Text="{Binding Path=ID}" VerticalAlignment="Center" />
                </Intersoft:FieldLabel>
                <Intersoft:FieldLabel Header="Price: " Name="fieldLabel2" HeaderWidth="70">
                    <TextBlock Name="textBlock3" Text="{Binding Path=Price}" VerticalAlignment="Center" />
                </Intersoft:FieldLabel>
                <Intersoft:FieldLabel Header="Author: " Name="fieldLabel3" HeaderWidth="70">
                    <TextBlock Name="textBlock4" VerticalAlignment="Center" Text="{Binding Path=Author}" />
                </Intersoft:FieldLabel>
                <Intersoft:FieldLabel Header="Category: " Name="fieldLabel4" HeaderWidth="70">
                    <TextBlock Name="textBlock5" Text="{Binding Path=Category}" VerticalAlignment="Center" />
                </Intersoft:FieldLabel>
            </Intersoft:UXStackPanel>
        </Intersoft:DockPanel>
    </Grid>
</Intersoft:UXPage>

BookDetail.xaml.cs

Sample Code
Copy Code
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using Intersoft.Client.UI.Navigation;
using ItemDetailUXFrame.ViewModels;

namespace ItemDetailUXFrame.Views
{
    public partial class BookDetail : UXPage
    {
        public BookDetail()
        {
            InitializeComponent();
        }

        // Executes when the user navigates to this page.
        protected override void OnNavigatedTo(NavigationEventArgs e)
        {
            if (this.NavigationContextExtended.QueryString.Count > 0)
            {
                string id = this.NavigationContextExtended.QueryString["ID"];

                if (!string.IsNullOrEmpty(id))
                {
                    BookListViewModel books = new BookListViewModel();
                    this.DataContext = books.FilteredBooks.SingleOrDefault(book => book.ID == id);
                }
            }
        }
    }
}

BookContainer.xaml

Sample Code
Copy Code
<Intersoft:UXPage 
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:Intersoft="http://intersoft.clientui.com/schemas"
    mc:Ignorable="d"
        x:Class="ItemDetailUXFrame.Views.BookContainer" 
        Title="BookContainer Page"
        d:DesignWidth="640" d:DesignHeight="480">
        
        <Grid x:Name="LayoutRoot">
        <Intersoft:UXJournalButtons VerticalAlignment="Top" Height="24" HorizontalAlignment="Left" ForwardButtonVisibility="Collapsed" Margin="10,0,0,0" NavigationTarget="{Binding ElementName=Frame1}" />
        <Intersoft:UXFrame x:Name="Frame1" HorizontalAlignment="Stretch" Margin="10,24,10,10" VerticalAlignment="Stretch" Source="/BookList" UseGlobalShell="True">
        <Intersoft:UXFrame.UriMapper>
            <Intersoft:UriMapper>
                <Intersoft:UriMapping Uri="/BookList" MappedUri="/ItemDetailUXFrame;ItemDetailUXFrame.Views.BookList"/>
                <Intersoft:UriMapping Uri="/Books/{ID}" MappedUri="/ItemDetailUXFrame;ItemDetailUXFrame.Views.BookDetail?ID={ID}"/>
            </Intersoft:UriMapper>
        </Intersoft:UXFrame.UriMapper>
        </Intersoft:UXFrame>
    </Grid>
</Intersoft:UXPage>
See Also

Concepts

Other Resources