Intersoft ClientUI Documentation
Walkthrough: Display Data in UXAccordion using MVVM Pattern

This walkthrough will show you how to display data to UXAccordion using MVVM pattern.

In this walkthrough, you perform the following tasks:

Prerequisites

You need the following components to complete this walkthrough:

Creating a new 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.

To add the data file

  1. In your project, create new folder with name Data.
  2. In Data folder, insert the data source from [Intersoft Installation Folder]\Intersoft WebUI Studio 2010 R1\Samples\SL4\ClientUI Samples\Intersoft.ClientUI.Samples.Assets\Data\BookDataSource.xml.
  3. Click on the BookDataSource.xml file and press F4 to open the Property Window. Change the Build Action property to Resources.

To add the resources file

  1. In your project, create new folder with name Assets.
  2. In Assets folder, create new folder with name Images.
  3. In Images folder, create new folder with name Books.
  4. In Books folder, copy the images from [Intersoft Installation Folder]\Intersoft WebUI Studio 2010 R1\Samples\SL4\ClientUI Samples\Intersoft.ClientUI.Samples.Assets\Images\Books\.

Creating the Model Pattern

This section shows you how to create the Book model class that represent the data entity used in this walkthrough. To create the Book model class, see Walkthrough: Creating Model for Book Data.

Creating the View

This section steps you through the process of creating the user interface that consists of UXAccordion.

To create the View pattern

  1. In your project, locate Views folder.
  2. In Views folder, add new Intersoft UXPage with name BooksList.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
  3. Open BooksList.xaml.
  4. Add a Grid and set the Width property to 520px and the Height property to 320px.
  5. Add UXAccordion control to the page and set the Padding property to 2,0 and Background property to #FFDFDFDF.
    XAML
    Copy Code
    <Grid Height="320" Width="520">
    
        <Intersoft:UXAccordion Name="uXAccordion1" Padding="2,0" Background="#FFDFDFDF">                
        </Intersoft:UXAccordion>
    
    </Grid>
  6. Create new ItemsPanelTemplate for your UXAccordionItem. This template will change the layout used for each UXAccordionItem
    XAML
    Copy Code
    <Intersoft:UXPage.Resources>
        ...
        <ItemsPanelTemplate x:Key="AccordionItemTemplate">
            <Intersoft:UXGridPanel Column="3" ItemHeight="100" ItemWidth="80"></Intersoft:UXGridPanel>
        </ItemsPanelTemplate>
        ...
    </Intersoft:UXPage.Resources>
  7. Create the styles for UXAccordionOption style and UXAccordionItem style inside the page resources.
    Apply the ItemsPanelTemplate you just created in UXAccordionItemStyle1.
    XAML
    Copy Code
    <Intersoft:UXPage.Resources>
        ...
        <Style x:Key="UXAccordionOptionStyle1" TargetType="Intersoft:UXAccordionOption">
            <Setter Property="ContentType" Value="Image"/>
            <Setter Property="ImageHeight" Value="NaN"/>
            <Setter Property="ImageWidth" Value="NaN"/>
        </Style>
        <Style x:Key="UXAccordionItemStyle1" TargetType="Intersoft:UXAccordionItem">
            <Setter Property="ItemContainerStyle" Value="{StaticResource UXAccordionOptionStyle1}"/>
            <Setter Property="ItemsPanel" Value="{StaticResource AccordionItemTemplate}" />
        </Style>
    </Intersoft:UXPage.Resources>
  8. Apply the ItemContainerStyle property of UXAccordion to the UXAccordionItemStyle1 that we created before inside the page's resources.
    XAML
    Copy Code
    <Grid x:Name="LayoutRoot">
        <Grid ...>
            <Intersoft:UXAccordion Name="uXAccordion1" ... ItemContainerStyle="{StaticResource UXAccordionItemStyle1}" ...>
    
            </Intersoft:UXAccordion>
        </Grid>
    </Grid>

Creating the ViewModel

This section steps you through the process of creating a ViewModel class that contains the properties to describe the View that you created in the previous section.

To create the BookViewModel class

  1. Create new BookViewModel class under ViewModels folder at your project that inherit ViewModelBase class. In the setter property, you will need to invoke OnPropertyChanged function.
    C#
    Copy Code
    public class BookViewModel : ViewModelBase
    {
        // Fields
        private Book _book;
    
        // Constructor
        public BookViewModel()
        {
        }
    
        public BookViewModel(Book book)
        {
            _book = book;
        }
    
        // Views
        public Book Book
        {
            get { return this._book; }
            set
            {
                if (this._book != value)
                {
                    this._book = value;
                    OnPropertyChanged("Book");
                }
            }
        }
    
        public string Title
        {
            get { return this.Book.Title; }
        }
    }
  2. Create new BookCategoryViewModel class under ViewModels folder at your project that inherit ViewModelBase class. In the setter property, you will need to invoke OnPropertyChanged function.
    C#
    Copy Code
    public class BookCategoryViewModel : ViewModelBase
    {
        // Fields
        private ObservableCollection<BookViewModel> _books;
        private string _name;
    
        // Constructor
        public BookCategoryViewModel()
        {
        }
    
        public BookCategoryViewModel(string name)
        {
            this._name = name;
        }
    
        public ObservableCollection<BookViewModel> Books
        {
            get
            {
                if (this._books == null)
                    this._books = new ObservableCollection<BookViewModel>();
    
                return this._books;
            }
        }
    
        public string Name
        {
            get { return this._name; }
            set
            {
                if (this._name != value)
                {
                    this._name = value;
                    this.OnPropertyChanged("Name");
                }
            }
        }
    }
  3. Create new BooksListViewModel class under ViewModels folder at your project that inherit ViewModelBase class.
  4. In this ViewModel, you add the LoadData method to get the data from BookDataSource.xml and stored in Categories property. 
    C#
    Copy Code
    public ObservableCollection<BookCategoryViewModel> Categories { get; set; }
    
    // Constructors
    public BooksListViewModel()
    {
        this.LoadBooks();
    }
    
    // Methods
    private void LoadBooks()
    {
        // loads book data from xml file
        StreamResourceInfo resource = System.Windows.Application.GetResourceStream(
                new Uri("MVVMWithUXAccordion;component/Data/BookDataSource.xml", UriKind.Relative));
    
        XDocument doc = XDocument.Load(resource.Stream);
    
        var books = from x in doc.Descendants("Book")
                    select new Book(x);
    
        this.Categories = new ObservableCollection<BookCategoryViewModel>();
    
        Dictionary<string, BookCategoryViewModel> dictionary = new Dictionary<string, BookCategoryViewModel>();
    
        foreach (Book book in books)
        {
            BookViewModel vm = new BookViewModel(book);
    
            if (dictionary.ContainsKey(book.Category))
            {
                BookCategoryViewModel category = dictionary[book.Category];
                category.Books.Add(vm);
            }
            else
            {
                BookCategoryViewModel category = new BookCategoryViewModel(book.Category);
                category.Books.Add(vm);
    
                dictionary.Add(book.Category, category);
                this.Categories.Add(category);
            }
        }
    
        resource.Stream.Close();
    }

Binding the ViewModel class to View

In the previous sections, you have learned how to create the Model and ViewModel classes, as well as the View that contains the user interface and controls used in this walkthrough. This section shows how to instantiate the ViewModel in the XAML page and bind the UI elements to the properties in the ViewModel.

To bind the ViewModel pattern

  1. Open the BooksList.xaml
  2. Declare the namespace that maps to the BooksListViewModel class in the BooksList.xaml page.
    XAML
    Copy Code
    <Intersoft:UXPage 
            ...
            xmlns:ViewModels="clr-namespace:MVVMWithUXAccordion.ViewModels"
            ...>
  3. Instantiate a new instance of the BooksListViewModel class in the UXPage resources and name it BooksData.
    XAML
    Copy Code
    <Intersoft:UXPage...>
    
        <Intersoft:UXPage.Resources>
            <ViewModels:BooksListViewModel x:Key="BooksData" />
        </Intersoft:UXPage.Resources>
    
        ...
    
    </Intersoft:UXPage>
  4. In the first Grid under LayoutRoot grid, click properties window.
  5. Locate the DataContext property, click the ellipsis button in the header property column, a context menu will appear, select the Apply DataBinding options and select BooksData.

    XAML
    Copy Code
    <Grid x:Name="LayoutRoot">
        <Grid Height="320" Width="520" DataContext="{Binding Source={StaticResource BooksData}}">
            
        </Grid>
    </Grid>
  6. In the first UXAccordion properties window.
    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 Categories

    XAML
    Copy Code
    <Grid x:Name="LayoutRoot">
        <Grid ...>
            <Intersoft:UXAccordion Name="uXAccordion1" Padding="2,0" Background="#FFDFDFDF" ItemsSource="{Binding Path=Categories}">
    
            </Intersoft:UXAccordion>
        </Grid>
    </Grid>
  7. Set the following properties of the UXAccordion:
    DisplayMemberPath Name
    CollectionMemberPath Books
    OptionDisplayMemberPath Title
    OptionImageMemberPath Book.Image
    SelectedIndex 2
    ExpandDirection Right

    XAML
    Copy Code
    <Grid x:Name="LayoutRoot">
        <Grid ...>
            <Intersoft:UXAccordion Name="uXAccordion1" Padding="2,0" Background="#FFDFDFDF" ItemsSource="{Binding Path=Categories}" DisplayMemberPath="Name" CollectionMemberPath="Books" OptionDisplayMemberPath="Title" OptionImageMemberPath="Book.Image" SelectedIndex="2" ExpandDirection="Right">
    
            </Intersoft:UXAccordion>
        </Grid>
    </Grid>
  8. Finally, save and run the project

Conclusion

In this walkthrough, you have learned how to create ClientUI MVVM Application project using Intersoft ClientUI MVVM Application project template, and create the classes and page based on the Model, View and ViewModel pattern. You also learned how to bind UXAccordion to a collection of books that are grouped by category.

To learn more about UI development using MVVM pattern, see MVVM Pattern Overview.

Complete Code Listing

This section lists the complete code used in this walkthrough.

Book.cs

C#
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 MVVMWithUXAccordion.ViewModels;
using System.Xml.Linq;

namespace MVVMWithUXAccordion.Models
{
    public class Book:ModelBase
    {
        #region Constructors

        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("/MVVMWithUXAccordion;component/Images/Books/" + x.Element("Image").Value.Trim(), UriKind.RelativeOrAbsolute);
        }

        #endregion

        #region Fields

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

        #endregion

        #region Properties

        public bool EnableValidation { get; set; }

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

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

                    if (EnableValidation && string.IsNullOrEmpty(this.Title))
                        SetError("Title", "Title is required");

                    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;
                    ClearError("Price");

                    if (EnableValidation && (double.IsNaN(this.Price) || this.Price == 0.0))
                        SetError("Price", "Price is required");

                    OnPropertyChanged("Price");
                }
            }
        }

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

        #endregion
    }
}

BookViewModel.cs

C#
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 MVVMWithUXAccordion.Models;

namespace MVVMWithUXAccordion.ViewModels
{
    public class BookViewModel : ViewModelBase
    {
        // Fields
        private Book _book;

        // Constructor
        public BookViewModel()
        {
        }

        public BookViewModel(Book book)
        {
            _book = book;
        }

        // Views
        public Book Book
        {
            get { return this._book; }
            set
            {
                if (this._book != value)
                {
                    this._book = value;
                    OnPropertyChanged("Book");
                }
            }
        }

        public string Title
        {
            get { return this.Book.Title; }
        }
    }
}

BookCategoryViewModel.cs

C#
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 System.Collections.ObjectModel;

namespace MVVMWithUXAccordion.ViewModels
{
    public class BookCategoryViewModel : ViewModelBase
    {
        // Fields
        private ObservableCollection<BookViewModel> _books;
        private string _name;

        // Constructor
        public BookCategoryViewModel()
        {
        }

        public BookCategoryViewModel(string name)
        {
            this._name = name;
        }

        public ObservableCollection<BookViewModel> Books
        {
            get
            {
                if (this._books == null)
                    this._books = new ObservableCollection<BookViewModel>();

                return this._books;
            }
        }

        public string Name
        {
            get { return this._name; }
            set
            {
                if (this._name != value)
                {
                    this._name = value;
                    this.OnPropertyChanged("Name");
                }
            }
        }
    }
}

BooksListViewModel.cs

C#
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 Intersoft.Client.Framework.Input;
using System.Collections.ObjectModel;
using System.Windows.Resources;
using System.Xml.Linq;
using System.Linq;
using MVVMWithUXAccordion.Models;
using System.Collections.Generic;

namespace MVVMWithUXAccordion.ViewModels
{
    public class BooksListViewModel : ViewModelBase
    {
        // Views
        public ObservableCollection<BookViewModel> Books { get; set; }
        public ObservableCollection<BookCategoryViewModel> Categories { get; set; }

        // Constructors
        public BooksListViewModel()
        {
            this.LoadBooks();
        }

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

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

            var books = from x in doc.Descendants("Book")
                        select new Book(x);

            this.Categories = new ObservableCollection<BookCategoryViewModel>();

            Dictionary<string, BookCategoryViewModel> dictionary = new Dictionary<string, BookCategoryViewModel>();

        if (dictionary.ContainsKey(book.Category))
            {
                BookViewModel vm = new BookViewModel(book);

                this.Books.Add(vm);
                {
                    BookCategoryViewModel category = dictionary[book.Category];
                    category.Books.Add(vm);
                }
                else
                {
                    BookCategoryViewModel category = new BookCategoryViewModel(book.Category);
                    category.Books.Add(vm);

                    dictionary.Add(book.Category, category);
                    this.Categories.Add(category);
                }
            }

            resource.Stream.Close();
        }

        protected virtual void InvalidateCommands()
        {
        }
    }
}

BooksList.xaml

XAML
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"
    xmlns:ViewModels="clr-namespace:MVVMWithUXAccordion.ViewModels"
        mc:Ignorable="d"
        x:Class="MVVMWithUXAccordion.Views.BooksList" 
        Title="BooksList Page"
        d:DesignWidth="640" d:DesignHeight="480">

    <Intersoft:UXPage.Resources>
        <ViewModels:BooksListViewModel x:Key="BooksData" />
        <ItemsPanelTemplate x:Key="AccordionItemTemplate">
            <Intersoft:UXGridPanel Column="3" ItemHeight="100" ItemWidth="80"></Intersoft:UXGridPanel>
        </ItemsPanelTemplate>
        <Style x:Key="UXAccordionOptionStyle1" TargetType="Intersoft:UXAccordionOption">
            <Setter Property="ContentType" Value="Image"/>
            <Setter Property="ImageHeight" Value="NaN"/>
            <Setter Property="ImageWidth" Value="NaN"/>
        </Style>
        <Style x:Key="UXAccordionItemStyle1" TargetType="Intersoft:UXAccordionItem">
            <Setter Property="ItemContainerStyle" Value="{StaticResource UXAccordionOptionStyle1}"/>
            <Setter Property="ItemsPanel" Value="{StaticResource AccordionItemTemplate}" />
        </Style>
    </Intersoft:UXPage.Resources>

    <Grid x:Name="LayoutRoot">
        <Grid Height="320" Width="520" DataContext="{Binding Source={StaticResource BooksData}}">
            <Intersoft:UXAccordion Name="uXAccordion1" Padding="2,0" Background="#FFDFDFDF" ItemsSource="{Binding Path=Categories}" ItemContainerStyle="{StaticResource UXAccordionItemStyle1}" DisplayMemberPath="Name" CollectionMemberPath="Books" OptionDisplayMemberPath="Title" OptionImageMemberPath="Book.Image" SelectedIndex="2" ExpandDirection="Right">

            </Intersoft:UXAccordion>
        </Grid>
    </Grid>
</Intersoft:UXPage>
See Also

Concepts

Other Resources