This walkthrough shows you how to use MVVM pattern to create a linked UXComboBox and show detailed info for the selected item. This walkthrough demonstrates the following concept:
- Create MVVM application using Intersoft ClientUI MVVM Application project template.
- Create the Model class that represents the Font data entity.
- Create the View page that represents the user interface of the application.
- Create the ViewModel class that describes the View.
- Bind the properties of UI controls in the View, such as the ItemsSource property of the UXComboBox, to the ViewModel.
- Populate the FontWeights combo box based on the selection in Font combo box.
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 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
- 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 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\FontDataSource.xml.
- Click on the FontDataSource.xml file and press F4 to open the Property Window. Change the Build Action property to Resources.
Creating the Model class
This section shows how to create a Model class in Font.cs and FontWeight.cs. The model will map each information in the data entity to a property.
To create the FontWeight model
- Create a new FontWeight.cs under the Models folder and inherit the ModelBase class.
- Create a private variable and a public property for Name node with a String data type. In the setter property, OnPropertyChanged method must be called after the property is assigned a new value.
- Repeat the same step for Price node.
C# Copy Code
private string _name; private string _price; public string Name { get { return _name; } set { if (_name != value) { _name = value; OnPropertyChanged("Name"); } } } public string Price { get { return _price; } set { if (_price != value) { _price = value; OnPropertyChanged("Price"); } } }
To create the Font model
- Create a new Font.cs under the Models folder and inherit the ModelBase class.
- Create a private variable and a public property for Name node with a String data type. In the setter property, OnPropertyChanged method must be called after the property is assigned a new value.
- Repeat the same step for FontWeights node using collection of FontWeight model as the data type.
C# Copy Code
private string _name; private ObservableCollection<FontWeight> _fontWeights; public string Name { get { return _name; } set { if (_name != value) { _name = value; OnPropertyChanged("Name"); } } } public ObservableCollection<FontWeight> FontWeights { get { return _fontWeights; } set { if (_fontWeights != value) { _fontWeights = value; OnPropertyChanged("FontWeights"); } } }
- Create a constructor which accept XElement parameter. The constructor maps information in the data entity to each property in the class.
C# Copy Code
public Font(XElement h) { Name = h.Element("Name").Value.ToString(); FontWeights = new ObservableCollection<FontWeight>(); foreach (XElement fontWeight in h.Descendants("FontWeight")) { FontWeights.Add(new FontWeight() { Name = fontWeight.Element("Name").Value.ToString(), Price = fontWeight.Element("Price").Value.ToString() }); } }
Creating the View
This section shows how to create a View pattern used in the application interface using LinkCombo.xaml. We bind the data to the control in later section
To create the LinkCombo view
- Add a new UXPage to the Views folder in your Silverlight project and name it LinkCombo.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 - Add a UXStackPanel.
- Add two FieldLabel control and a TextBlock control to the page.
- Set the Header property to Select Font: in the first FieldLabel. On the second FieldLabel set it to Select FontWeight:.
- Set the following properties in the UXStackPanel.
Property Value Width Auto Height Auto Orientation Vertical - Set FieldLabel Content property to use UXComboBox. The project will automatically reference Intersoft.Client.UI.Aqua.UXCollection if the control is added using toolbox.
Creating the ViewModel
This section shows how to create a ViewModel to hold the collection of Font and FontWeight model object. There is also properties to hold the UXComboBox SelectedItem and selection summary.
To create the LinkComboViewModel ViewModel
- Create a new LinkComboViewModel.cs under the ViewModels folder and inherit the ViewModelBase class.
- Create a private variable and a public property to hold collection of Font object. In the setter property, OnPropertyChanged method must be called after the property is assigned a new value.
C# Copy Code
private ObservableCollection<Font> _fonts; public ObservableCollection<Font> Fonts { get { return _fonts; } set { if (_fonts != value) { _fonts = value; OnPropertyChanged("Fonts"); } } }
- Repeat the same step for collection of FontWeight object.
- Create a private variable and a public property to hold the selected Font object. In the setter property, OnPropertyChanged method must be called after the property is assigned a new value.
C# Copy Code
private Font _selectedFont; public Font SelectedFont { get { return _selectedFont; } set { if (_selectedFont != value) { _selectedFont = value; OnPropertyChanged("SelectedFont"); } } }
- Repeat the same step for selected FontWeight object.
- Create a private variable and a public property to hold the selected Models summary. In the setter property, OnPropertyChanged method must be called after the property is assigned a new value.
C# Copy Code
private string _priceInfo; public string PriceInfo { get { return _priceInfo; } set { if (_priceInfo != value) { _priceInfo = value; OnPropertyChanged("PriceInfo"); } } }
- Create a LoadData method to fill the Fonts collection based on the data from FontDataSource.xml. This method is called during object construction.
C# Copy Code
public LinkComboViewModel() { LoadData(); } public void LoadData() { StreamResourceInfo resource = System.Windows.Application.GetResourceStream( new Uri("LinkUXComboBoxMVVM;component/Data/FontDataSource.xml",UriKind.Relative)); XDocument doc = XDocument.Load(resource.Stream); Fonts = new ObservableCollection<Font>(); foreach(XElement font in doc.Descendants("Font")) { Fonts.Add(new Font(font)); } resource.Stream.Close(); }
- Modify the SelectedFont property to set the FontWeights collection based on the SelectedFont and reset the PriceInfo property.
C# Copy Code
public Font SelectedFont { get { return _selectedFont; } set { if (_selectedFont != value) { _selectedFont = value; if (_selectedFont != null) FontWeights = _selectedFont.FontWeights; PriceInfo = ""; OnPropertyChanged("SelectedFont"); } } }
- Modify the SelectedFontWeight property to set the PriceInfo based on the SelectedFont Name, SelectedtFontWeight Name and Price detail.
C# Copy Code
public FontWeight SelectedFontWeight { get { return _selectedFontWeight; } set { if (_selectedFontWeight != value) { _selectedFontWeight = value; PriceInfo = string.Format("{0} {1} {2}", SelectedFont.Name, _selectedFontWeight.Name, _selectedFontWeight.Price); OnPropertyChanged("SelectedFontWeight"); } } }
Binding the ViewModel to View
This section shows how to bind the ViewModel property object to the LinkCombo page.
To bind the LinkComboViewModel ViewModel
- Declare the namespace that maps to the LinkComboViewModel class.
XAML Copy Code
<Intersoft:UXPage ... xmlns:ViewModels="clr-namespace:LinkUXComboBoxMVVM.ViewModels" ... > ... </Intersoft:UXPage>
- Reference the LinkComboViewModel as the page DataContext.
XAML Copy Code
<Intersoft:UXPage.DataContext> <ViewModels:LinkComboViewModel /> </Intersoft:UXPage.DataContext>
- In the first UXComboBox 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 Fonts
- Click the ellipsis button in the header property column, a context menu will appear
- Select the Apply DataBinding Options...
- From the Tab Path, select SelectedFont
- From the Tab Options, set Mode to TwoWay
XAML Copy Code
<Intersoft:UXComboBox Name="uXComboBox1" Width="175" ItemsSource="{Binding Path=Fonts}" DisplayMemberPath="Name" SelectedItem="{Binding Path=SelectedFont, Mode=TwoWay}" />
- In the second UXComboBox 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 FontWeights
- Click the ellipsis button in the header property column, a context menu will appear
- Select the Apply DataBinding Options...
- From the Tab Path, select SelectedFontWeight
- From the Tab Options, set Mode to TwoWay
XAML Copy Code
<Intersoft:UXComboBox Name="uXComboBox2" Width="175" SelectedItem="{Binding Path=SelectedFontWeight, Mode=TwoWay}" DisplayMemberPath="Name" ItemsSource="{Binding Path=FontWeights}" />
- In the TextBlock 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 PriceInfo
Viewing the Result
In order to view the result, you will need to build the Silverlight project and run the test page in browser.
To view the result
- FontWeight UXComboBox will only show collection of FontWeight based on the Font selection.
- The TextBlock control will show the summary of the selected item.
Conclusion
In this walkthrough, you have learned how to create ClientUI MVVM Application project using Intersoft ClientUI MVVM Application project template, and create classes with page based on the MVVM pattern. You also learned how to linked two UXComboBox.
For more information about application development using MVVM pattern, see MVVM Pattern Overview
Complete Code Listing
This section lists the complete code used in this walkthrough.
FontWeight.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 LinkUXComboBoxMVVM.ViewModels; namespace LinkUXComboBoxMVVM.Models { public class FontWeight: ModelBase { private string _name; private string _price; public string Name { get { return _name; } set { if (_name != value) { _name = value; OnPropertyChanged("Name"); } } } public string Price { get { return _price; } set { if (_price != value) { _price = value; OnPropertyChanged("Price"); } } } public FontWeight() { } } } |
Font.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 LinkUXComboBoxMVVM.ViewModels; using System.Xml.Linq; using System.Collections.ObjectModel; namespace LinkUXComboBoxMVVM.Models { public class Font: ModelBase { private string _name; private ObservableCollection<FontWeight> _fontWeights; public string Name { get { return _name; } set { if (_name != value) { _name = value; OnPropertyChanged("Name"); } } } public ObservableCollection<FontWeight> FontWeights { get { return _fontWeights; } set { if (_fontWeights != value) { _fontWeights = value; OnPropertyChanged("FontWeights"); } } } public Font(XElement h) { Name = h.Element("Name").Value.ToString(); FontWeights = new ObservableCollection<FontWeight>(); foreach (XElement fontWeight in h.Descendants("FontWeight")) { FontWeights.Add(new FontWeight() { Name = fontWeight.Element("Name").Value.ToString(), Price = fontWeight.Element("Price").Value.ToString() }); } } } } |
LinkComboViewModel.cs
C# | ![]() |
---|---|
using System; using System.Net; 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 LinkUXComboBoxMVVM.Models; using System.Windows.Resources; using System.Xml.Linq; namespace LinkUXComboBoxMVVM.ViewModels { public class LinkComboViewModel : ViewModelBase { private ObservableCollection<Font> _fonts; private ObservableCollection<FontWeight> _fontWeights; private Font _selectedFont; private FontWeight _selectedFontWeight; private string _priceInfo; public ObservableCollection<Font> Fonts { get { return _fonts; } set { if (_fonts != value) { _fonts = value; OnPropertyChanged("Fonts"); } } } public ObservableCollection<FontWeight> FontWeights { get { return _fontWeights; } set { if (_fontWeights != value) { _fontWeights = value; OnPropertyChanged("FontWeights"); } } } public Font SelectedFont { get { return _selectedFont; } set { if (_selectedFont != value) { _selectedFont = value; if (_selectedFont != null) FontWeights = _selectedFont.FontWeights; PriceInfo = ""; OnPropertyChanged("SelectedFont"); } } } public FontWeight SelectedFontWeight { get { return _selectedFontWeight; } set { if (_selectedFontWeight != value) { _selectedFontWeight = value; PriceInfo = string.Format("{0} {1} {2}", SelectedFont.Name, _selectedFontWeight.Name, _selectedFontWeight.Price); OnPropertyChanged("SelectedFontWeight"); } } } public string PriceInfo { get { return _priceInfo; } set { if (_priceInfo != value) { _priceInfo = value; OnPropertyChanged("PriceInfo"); } } } // Constructors public LinkComboViewModel() { LoadData(); } public void LoadData() { StreamResourceInfo resource = System.Windows.Application.GetResourceStream( new Uri("LinkUXComboBoxMVVM;component/Data/FontDataSource.xml",UriKind.Relative)); XDocument doc = XDocument.Load(resource.Stream); Fonts = new ObservableCollection<Font>(); foreach(XElement font in doc.Descendants("Font")) { Fonts.Add(new Font(font)); } resource.Stream.Close(); } } } |
LinkCombo.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:LinkUXComboBoxMVVM.ViewModels" mc:Ignorable="d" x:Class="LinkUXComboBoxMVVM.Views.LinkCombo" Title="LinkCombo Page" d:DesignWidth="640" d:DesignHeight="480"> <Intersoft:UXPage.DataContext> <ViewModels:LinkComboViewModel /> </Intersoft:UXPage.DataContext> <Grid x:Name="LayoutRoot"> <Intersoft:UXStackPanel HorizontalAlignment="Left" Margin="10,10,0,0" Name="uXStackPanel1" VerticalAlignment="Top" Orientation="Vertical"> <Intersoft:FieldLabel Header="Select Font: " Name="fieldLabel1" HeaderWidth="125"> <Intersoft:UXComboBox Name="uXComboBox1" Width="175" ItemsSource="{Binding Path=Fonts}" DisplayMemberPath="Name" SelectedItem="{Binding Path=SelectedFont, Mode=TwoWay}" /> </Intersoft:FieldLabel> <Intersoft:FieldLabel Header="Select FontWeight: " Name="fieldLabel2" HeaderWidth="125"> <Intersoft:UXComboBox Name="uXComboBox2" Width="175" SelectedItem="{Binding Path=SelectedFontWeight, Mode=TwoWay}" DisplayMemberPath="Name" ItemsSource="{Binding Path=FontWeights}" /> </Intersoft:FieldLabel> <TextBlock Height="23" Name="textBlock1" Text="{Binding Path=PriceInfo}" /> </Intersoft:UXStackPanel> </Grid> </Intersoft:UXPage> |