This walkthrough shows you how to use MVVM pattern to show detailed info for the selected item of UXFlow.
In this walkthrough, you perform the following tasks:
- Create ClientUI MVVM Application project using Intersoft ClientUI MVVM Application project template.
- Create the Model class that represents the Contact data entity.
- Create the View page that represents the user interface of the application.
- Create the ViewModel class that describes the View.
- Bind the ViewModel to the View.
Prerequisites
You need the following components to complete this walkthrough:
- Visual Studio 2010
- Silverlight 4 Tools for Visual Studio 2010
- Intersoft ClientUI
Creating a new ClientUI MVVM Project
The first step is to create a new ClientUI MVVM Application using Intersoft ClientUI MVVM project template in Visual Studio.
To create the ClientUI MVVM Application project
- Start Visual Studio 2010.
- 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.
- In project reference, add System.Xml.Linq.dll. This assembly is required to perform LINQ query to xml data.
To add the data file
- In your project, create a new folder with name Data.
- 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\HotelDataSource.xml.
- Click on the HotelDataSource.xml file and press F4 to open the Property Window. Change the BuildAction property to Resources.
To add the resources file
- In your project, create new folder with name Images.
- In Images folder, copy the images from [Intersoft Installation Folder]\Intersoft WebUI Studio 2010 R1\Samples\SL4\ClientUI Samples\Intersoft.ClientUI.Samples.Assets\Images\Hotels\
Next, you will create the Hotel model class that represent the data entity used in this walkthrough.
Creating Model Class
This section shows you how to create the Hotel model class that represents the data entity used in this walkthrough. The Hotel model class contains constructors to obtain the URI path of the hotel's image.
To create the Hotel Model class
- Create a Model class that inherits ModelBase class under the Models folder. You can name it Hotel.cs.
- Add Image property to the Hotel model class by defining the backing field with complete getter and setter in the property. In the setter property you will need to call OnPropertyChanged method after the backing field is assigned to the new value.
Sample Code Copy Code
private Uri _image; public Uri Image { get { return this._image; } set { if (this._image != value) { this._image = value; this.OnPropertyChanged("Image"); } } }
- Also add Location and Name property to the Hotel model class by repeating step number 2.
Sample Code Copy Code
public class Hotel : ViewModels.ModelBase { #region Fields private Uri _image; private string _location; private string _name; #endregion #region Properties public Uri Image { get { return this._image; } set { if (this._image != value) { this._image = value; this.OnPropertyChanged("Image"); } } } public string Location { get { return this._location; } set { if (this._location != value) { this._location = value; this.OnPropertyChanged("Location"); } } } public string Name { get { return this._name; } set { if (this._name != value) { this._name = value; this.OnPropertyChanged("Name"); } } } #endregion }
- Add constructor of the Hotel class.
Sample Code Copy Code
public Hotel() { } public Hotel(XElement h) : this() { string image = h.Element("Image").Value.Trim(); this._image = new Uri("/UXListBox-Walkthrough;component/Images/" + image, UriKind.RelativeOrAbsolute); this._location = h.Element("Location").Value.Trim(); this._name = h.Element("Name").Value.Trim(); }
Creating the View
This section show how to create a View used in the application interface. You will bind the data to the control in the later section.
To create the HotelList page
- Add a new UXPage to the Views folder in your Silverlight project and name it HotelList.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 - Open the newly created HotelList.xaml page and clear the content inside the LayoutRoot.
- Add a DockPanel.
Set the Height and Width property into Auto. - Add a UXFlow inside the DockPanel. Click on the Right section of the docking visual hint to dock the UXFlow to the right and click the Fill section of the docking visual hint to fill the UXFlow at the entire DockPanel. Set the Width property to Auto.
XAML Copy Code
<Intersoft:DockPanel Name="dockPanel1" FillChildMode="Custom"> <Intersoft:UXFlow Height="480" Name="uXFlow1" Intersoft:DockPanel.Dock="Right" Intersoft:DockPanel.IsFillElement="True"></Intersoft:UXFlow> </Intersoft:DockPanel>
- Add a DockPanel inside the previous DockPanel. Set the following properties on the second DockPanel.
Properties Value HorizontalAlignment Center VerticalAlignment Center DockPanel.Dock Left Height Auto
XAML Copy Code
<Intersoft:DockPanel Name="dockPanel1" FillChildMode="Custom"> ... <Intersoft:DockPanel Name="dockPanel2" Width="200" Intersoft:DockPanel.Dock="Left" HorizontalAlignment="Center" VerticalAlignment="Center" /> </Intersoft:DockPanel>
- Add a GlassLabel inside the second DockPanel. Set the following properties on the GlassLabel.
Properties Value DockPanel.Dock Top Width 200 Content Reset Value - Add a StackPanel inside the GlassLabel. Set the Height and Width property into Auto.
- Add a TextBlock. Set the HorizantalAlignment property to Center and FontSize property to 14.
- Repeat point number 6 once. Set the HorizantalAlignment property to Center and FontSize property to 11.
- Add a FieldLabel, put it inside the second DockPanel. Set the following properties on the first FieldLabel.
Properties Value DockPanel.Dock Top HorizontalAlignment Left Header Rating: - Repeat point number 8 once. Set the following properties on the second FieldLabel.
Properties Value DockPanel.Dock Top HorizontalAlignment Left Header Rate:
XAML Copy Code
<Intersoft:DockPanel Name="dockPanel1" FillChildMode="Custom"> <Intersoft:UXFlow Height="480" Name="uXFlow1" Intersoft:DockPanel.Dock="Right" Intersoft:DockPanel.IsFillElement="True"></Intersoft:UXFlow> <Intersoft:DockPanel Name="dockPanel2" Width="200" Intersoft:DockPanel.Dock="Left" HorizontalAlignment="Center" VerticalAlignment="Center" Intersoft:DockPanel.IsFillElement="True"> <Intersoft:GlassLabel Name="glassLabel1" Intersoft:DockPanel.Dock="Top" Width="200"> <StackPanel Name="stackPanel1"> <TextBlock Name="textBlock1" Text="TextBlock" HorizontalAlignment="Center" /> <TextBlock Name="textBlock2" Text="TextBlock" HorizontalAlignment="Center" /> </StackPanel> </Intersoft:GlassLabel> <Intersoft:FieldLabel Header="Rating: " Name="fieldLabel1" Intersoft:DockPanel.Dock="Top" HorizontalAlignment="Left"> <Intersoft:UXTextBox HorizontalAlignment="Left" Name="uXTextBox1" Text="UXTextBlock" VerticalAlignment="Top" /> </Intersoft:FieldLabel> <Intersoft:FieldLabel Header="Rate: " Name="fieldLabel2" Intersoft:DockPanel.Dock="Top" HorizontalAlignment="Left"> <Intersoft:UXTextBox HorizontalAlignment="Left" Name="uXTextBox2" Text="UXTextBlock" VerticalAlignment="Top" /> </Intersoft:FieldLabel> </Intersoft:DockPanel> </Intersoft:DockPanel>
- When run the project, The looks of the Views should be like down below.
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. The ViewModel defines the Hotels collection to represent an observable collection of Hotel model and a LoadData method to load hotel data from xml file.
To create the HotelListViewModel
- Add a new class to the ViewModels folder in your Silverlight project and name it HotelListViewModel.cs.
- Open HotelListViewModel.cs and inherit the class from ViewModelBase class.
Sample Code Copy Code
public class HotelListViewModel : ViewModelBase
- In this view mode, you add the Hotels properties which represent a collection of Hotel model. You also add SelectedItem such with type Hotel that will be bound to the SelectedItem property of UXFlow in the view, such as shown in the following code listing.
Sample Code Copy Code
public class HotelListViewModel : ViewModelBase { // Fields private Hotel _selectedItem = null; // Views public ObservableCollection<Hotel> Hotels { get; set; } // Selection, View States public Hotel SelectedItem { get { return _selectedItem; } set { if (_selectedItem != value) { _selectedItem = value; OnPropertyChanged("SelectedItem"); } } } // Constructor public HotelListViewModel() { this.LoadData(); } private void LoadData() { // loads hotel data from xml file StreamResourceInfo resource = System.Windows.Application.GetResourceStream( new Uri("UXListBox-Walkthrough;component/Data/HotelDataSource.xml", UriKind.Relative)); XDocument doc = XDocument.Load(resource.Stream); var hotels = from x in doc.Descendants("Hotel") select new Hotel(x); this.Hotels = new ObservableCollection<Hotel>(); foreach (Hotel hotel in hotels) { this.Hotels.Add(hotel); } resource.Stream.Close(); } }
Next, you will bind the HotelListViewModel to your HotelList.xaml.
Binding the ViewModel to View
This section shows how to bind the ViewModel that was created in the previous section to the View, for example you will bind the ItemsSource of UXFlow to Hotels property of the HotelListViewModel.
To bind the ViewModel to HotelList.xaml
- Declare the namespace that maps to the HotelListViewModel class in the HotelList page. .
XAML Copy Code
<Intersoft:UXPage ... > ... <Intersoft:UXPage.DataContext> <ViewModels:HotelListViewModel /> </Intersoft:UXPage.DataContext> ... </Intersoft:UXPage>
- In the UXFlow properties window.
Locate the ItemsSource property.- Click the ellipsis button in the header property column, a context menu will appear
- Select the Apply DataBinding options...
- From the Tab Path, select Hotels
- Click the ellipsis button in the header property column, a context menu will appear
- Select the Apply DataBinding pptions...
- From the Tab Path, select SelectedItem
- From the Tab Options, set Mode to TwoWay
Properties Value ImageMemberPath Image SubTitleMemberPath Location TitleMemberPath Name
XAML Copy Code
<Intersoft:DockPanel Name="dockPanel1" FillChildMode="Custom" DataContext="{Binding}"> <Intersoft:UXFlow Height="480" Name="uXFlow1" Intersoft:DockPanel.Dock="Right" Intersoft:DockPanel.IsFillElement="True" ItemsSource="{Binding Path=Hotels, Mode=TwoWay}" SelectedItem="{Binding Path=SelectedItem}" ImageMemberPath="Image" SubTitleMemberPath="Location" TitleMemberPath="Name"></Intersoft:UXFlow> ... </Intersoft:DockPanel>
- Locate dockPanel2, then open properties window.
Locate the DataContext property.- Click the ellipsis button in the header property column, a context menu will appear
- Select the Apply DataBinding options...
- From the Tab Path, select SelectedItem
XAML Copy Code
<Intersoft:DockPanel Name="dockPanel2" Width="200" Intersoft:DockPanel.Dock="Left" HorizontalAlignment="Center" VerticalAlignment="Center" DataContext="{Binding Path=SelectedItem}"> <Intersoft:GlassLabel Name="glassLabel1" Intersoft:DockPanel.Dock="Top" Width="200"> ... </Intersoft:DockPanel>
- Locate textBlock1, then open properties window.
Locate the Text property.- Click the ellipsis button in the header property column, a context menu will appear
- Select the Apply DataBinding options...
- From the Tab Path, select Name
XAML Copy Code
<StackPanel Name="stackPanel1"> <TextBlock Name="textBlock1" Text="{Binding Path=Name}" HorizontalAlignment="Center"/> ... </StackPanel>
- Locate textBlock2, then open properties window.
Locate the Text property.- Click the ellipsis button in the header property column, a context menu will appear
- Select the Apply DataBinding options...
- From the Tab Path, select Location
XAML Copy Code
<StackPanel Name="stackPanel1"> ... <TextBlock Name="textBlock2" Text="{Binding Path=Location}" HorizontalAlignment="Center"/> </StackPanel>
- Locate uXTextBox1, then open properties window.
Locate the Text property.- Click the ellipsis button in the header property column, a context menu will appear
- Select the Apply DataBinding options...
- From the Tab Path, select Rating
XAML Copy Code
<Intersoft:FieldLabel Header="Rating: " ... > <Intersoft:UXTextBox HorizontalAlignment="Left" Name="uXTextBox1" Text="{Binding Path=Rating}" VerticalAlignment="Top" /> </Intersoft:FieldLabel>
- Locate uXTextBox2, then properties window.
Locate the Text property.
- Click the ellipsis button in the header property column, a context menu will appear
- Select the Apply DataBinding options...
- From the Tab Path, select Rate
XAML Copy Code
<Intersoft:FieldLabel Header="Rate: " ... > <Intersoft:UXTextBox HorizontalAlignment="Left" Name="uXTextBox2" Text="{Binding Path=Rate}" VerticalAlignment="Top" /> </Intersoft:FieldLabel>
- This will be the final looks of Cover Flow.
Complete Code Listing
This section lists the complete code used in this walkthrough.
Hotel.cs
C# | ![]() |
---|---|
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.Xml.Linq; using CoverFlowMVVM.ViewModels; namespace CoverFlowMVVM.Models { public class Hotel: ModelBase { #region Constructors public Hotel(XElement h) { string image = h.Element("Image").Value.Trim(); this._image = new Uri("/CoverFlowMVVM;component/Assets/Images/" + image, UriKind.RelativeOrAbsolute); this._location = h.Element("Location").Value.Trim(); this._name = h.Element("Name").Value.Trim(); this._rate = h.Element("Rate").Value.Trim(); this._rating = h.Element("Rating").Value.Trim(); } #endregion #region Fields private Uri _image; private string _location; private string _name; private string _rate; private string _rating; #endregion #region Properties public Uri Image { get { return this._image; } set { if (this._image != value) { this._image = value; this.OnPropertyChanged("Image"); } } } public string Location { get { return this._location; } set { if (this._location != value) { this._location = value; this.OnPropertyChanged("Location"); } } } public string Name { get { return this._name; } set { if (this._name != value) { this._name = value; this.OnPropertyChanged("Name"); } } } public string Rate { get { return this._rate; } set { if (this._rate != value) { this._rate = value; this.OnPropertyChanged("Rate"); } } } public string Rating { get { return this._rating; } set { if (this._rating != value) { this._rating = value; this.OnPropertyChanged("Rating"); } } } #endregion } } |
HotelList.xaml
XAML | ![]() |
---|---|
<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:CoverFlowMVVM.ViewModels" mc:Ignorable="d" x:Class="CoverFlowMVVM.Views.HotelList" Title="HotelList Page" d:DesignWidth="640" d:DesignHeight="480"> <Intersoft:UXPage.DataContext> <ViewModels:HotelListViewModel /> </Intersoft:UXPage.DataContext> <Grid x:Name="LayoutRoot"> <Intersoft:DockPanel Name="dockPanel1" FillChildMode="Custom"> <Intersoft:UXFlow Height="480" Name="uXFlow1" Intersoft:DockPanel.Dock="Right" Intersoft:DockPanel.IsFillElement="True" ItemsSource="{Binding Path=Hotels, Mode=TwoWay}" ImageMemberPath="Image" SubTitleMemberPath="Location" TitleMemberPath="Name" SelectedItem="{Binding Path=SelectedItem, Mode=TwoWay}"></Intersoft:UXFlow> <Intersoft:DockPanel Name="dockPanel2" Width="200" Intersoft:DockPanel.Dock="Left" HorizontalAlignment="Center" VerticalAlignment="Center" DataContext="{Binding Path=SelectedItem}" Intersoft:DockPanel.IsFillElement="True"> <Intersoft:GlassLabel Name="glassLabel1" Intersoft:DockPanel.Dock="Top" Width="200"> <StackPanel Name="stackPanel1"> <TextBlock Name="textBlock1" Text="{Binding Path=Name}" HorizontalAlignment="Center" /> <TextBlock Name="textBlock2" Text="{Binding Path=Location}" HorizontalAlignment="Center" /> </StackPanel> </Intersoft:GlassLabel> <Intersoft:FieldLabel Header="Rating: " Name="fieldLabel1" Intersoft:DockPanel.Dock="Top" HorizontalAlignment="Left"> <Intersoft:UXTextBox HorizontalAlignment="Left" Name="uXTextBox1" Text="{Binding Path=Rating}" VerticalAlignment="Top" /> </Intersoft:FieldLabel> <Intersoft:FieldLabel Header="Rate: " Name="fieldLabel2" Intersoft:DockPanel.Dock="Top" HorizontalAlignment="Left"> <Intersoft:UXTextBox HorizontalAlignment="Left" Name="uXTextBox2" Text="{Binding Path=Rate}" VerticalAlignment="Top" /> </Intersoft:FieldLabel> </Intersoft:DockPanel> </Intersoft:DockPanel> </Grid> </Intersoft:UXPage> |
HotelListViewModel.cs
C# | ![]() |
---|---|
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 CoverFlowMVVM.Models; using System.Windows.Resources; using System.Xml.Linq; using System.Linq; namespace CoverFlowMVVM.ViewModels { public class HotelListViewModel : ViewModelBase { // Fields private Hotel _selectedItem = null; // Views public ObservableCollection<Hotel> Hotels { get; set; } // Selection, View States public Hotel SelectedItem { get { return _selectedItem; } set { if (_selectedItem != value) { _selectedItem = value; OnPropertyChanged("SelectedItem"); } } } // Constructor public HotelListViewModel() { this.LoadData(); } private void LoadData() { // loads hotel data from xml file StreamResourceInfo resource = System.Windows.Application.GetResourceStream( new Uri("UXListBox-Walkthrough;component/Data/HotelDataSource.xml", UriKind.Relative)); XDocument doc = XDocument.Load(resource.Stream); var hotels = from x in doc.Descendants("Hotel") select new Hotel(x); this.Hotels = new ObservableCollection<Hotel>(); foreach (Hotel hotel in hotels) { this.Hotels.Add(hotel); } resource.Stream.Close(); } } } |