MOBILE

Windows Phone 7 Advanced Programming Model : Advanced Data Binding (part 1)

9/20/2011 3:40:02 PM
In this article, I cover how to access Syndicated Services like RSS feeds from Windows Phone 7, as well as advanced Model-View-ViewModel (MVVM) techniques to incorporate page navigation, showing progress, and lazy loading images. The last subsection covers the IValueConverter interface, which allows you to data bind any data type to just about any other data.

A sample project based on the MVVM Light project template named AdvancedDataBinding is added to solution. MVVM is leveraged for this example to demonstrate how to handle slightly additional complexity of separating concerns between the View and the ViewModel when dealing with more complex scenarios.

By default, the MainPage.xaml binds to the MainViewModel in the ViewModel folder. MainPage.xaml presents a menu of four items that navigate to individual pages corresponding to the sections that follow:

  • Syndicated Services (/View/SyndicatedServices.xaml)

  • Showing Progress (/View/ShowingProgress.xaml)

  • Lazy Load Images (/View/LazyLoadImages.xaml)

  • Data Bind to Anything (/View/DatabindToAnything.xaml)

MainPage.xaml consists of a ListBoxdatabound to a collection of items that represent the above pages. Here is the XAML:

<ListBox x:Name="listBox1" Margin="24,0,0,0"
ItemsSource="{Binding Pages}"
ItemTemplate="{StaticResource PageItemTemplate}" />

In MainViewModel.cs, the ApplicationTitle and PageName properties are updated for the current project. A Pages property is added to MainViewModel class that is of type List<PageItemViewModel>:

public const string PagesPropertyName = "Pages";
private List<PageItemViewModel> _pages = null;
public List<PageItemViewModel> Pages
{
get
{
return _pages;
}

protected set
{
if (_pages == value)
{
return;
}

var oldValue = _pages;
_pages = value;

// Update bindings, no broadcast
RaisePropertyChanged(PagesPropertyName);
}
}

The MainViewModel class has a method named LoadPageInfo(), which instantiates the Pages collection:

private void LoadPagesInfo()
{
Pages = new List<PageItemViewModel>()
{
new PageItemViewModel(){PageTitle="syndicated services",
PageUri=new Uri("/View/SyndicatedServices.xaml",UriKind.Relative)},
new PageItemViewModel(){PageTitle="showing progress",
PageUri=new Uri("/View/ShowingProgress.xaml",UriKind.Relative)},
new PageItemViewModel(){PageTitle="lazy load images",
PageUri=new Uri("/View/LazyLoadImages.xaml",UriKind.Relative)},
new PageItemViewModel(){PageTitle="data binding to anything",
PageUri=new Uri("/View/DatabindToAnything.xaml",UriKind.Relative)}
};
}

Normally, the PageItem class would be a simple Model class; however, I made it a ViewModel class because of necessary support to allow databinding and navigation from a ListBox displaying the Pages data. When an item is selected in the ListBox shown in Figure 6-1, the application should navigate to the associated page. We don't want to write code to do this in the MainPage.xaml.cs code-behind file. Instead we take advantage of messaging and commanding support provided by the MVVM Light toolkit.

Figure 1. AdvancedDataBinding MainPage.xaml UI

The selected item in the ListBox on MainPage.xaml should perform navigation to the associated page pointed to by the selected item. This means that the Commanding support is required at the PageItem / ItemTemplate level, not at the ListBox level. To support this functionality, a ViewModel class named PageItemViewModel is added that supports GalaSoft Light Messaging and Commanding . Listing 1 shows the PageItemViewModel.

Example 1. PageItemViewModel Class File
using System;
using GalaSoft.MvvmLight.Command;
using GalaSoft.MvvmLight.Messaging;
using GalaSoft.MvvmLight;
namespace AdvancedDataBinding.ViewModel
{
public class PageItemViewModel : ViewModelBase
{
public PageItemViewModel()
{
//Wire up the NavigateToPageCommand RelayCommand to send the message
//for the Uri of the page to navigate to.
NavigateToPageCommand = new RelayCommand<Uri>(

param => SendNavigationRequestMessage(param));
}

#region PageItem properties
public const string PageTitlePropertyName = "PageTitle";
private string _pageTitle = null;
public string PageTitle
{
get
{
return _pageTitle;
}
set
{
if (_pageTitle == value)
{
return;
}

var oldValue = _pageTitle;
_pageTitle = value;
RaisePropertyChanged(PageTitlePropertyName);
}
}


public const string PageUriPropertyName = "PageUri";
private Uri _pageUri = null;
public Uri PageUri
{
get
{
return _pageUri;
}
set
{
if (_pageUri == value)
{
return;
}

var oldValue = _pageUri;
_pageUri = value;

// Update bindings, no broadcast
RaisePropertyChanged(PageUriPropertyName);
}
}
#endregion

#region Commanding and Messaging
public RelayCommand<Uri> NavigateToPageCommand
{
get;


private set;
}

protected void SendNavigationRequestMessage(Uri uri)
{
Messenger.Default.Send<Uri>(uri, "PageNavRequest");
}
#endregion
}
}

The PageItemViewModel class is broken up into two sections, one for the properties and the other for the Commanding and Messaging support. The PageItemViewModel class has two properties, PageTitle and PageUri. The PageUri points to the appropriate XAML file to navigate to for the PageTitle property value.

The Commanding and Messaging support is pretty simple code. The NavigateToPageCommand is what the MainPage.xaml View DataBinds to when the ListBoxItem is clicked via the MVVM Light EventToCommand Behavior. The NavigateToPageCommandRelayCommand<T> is connected to the MVVM Light Messaging infrastructure via this code in the PageItemViewModel constructor:

NavigateToPageCommand = new RelayCommand<Uri>(
param => SendNavigationRequestMessage(param));

The NavigateToPageCommand takes an Uri and passes it to the SendNavigationRequestMessage. This is a bit of indirection, as the Uri property comes from the ListBox's template and then is sent back to the View via the MVVM Light Messaging infrastructure but it does promote decoupling of the UI from the ViewModel.

The MainPage.xaml View receives the message via this line of code added to the PhoneApplicationPage constructor and uses an inline Lambda statement to call the NavigationService:

Messenger.Default.Register<Uri>(
this, "PageNavRequest",
(uri) => NavigationService.Navigate(uri));

I mentioned earlier that the DataTemplate data binds to the NavigateToPageCommand. Here is the ItemTemplate="{StaticResourcePageItemTemplate}" for the MainPage.ListBox control:

<DataTemplate x:Key="PageItemTemplate">
<Grid Margin="0,15">
<TextBlock Margin="0,0,1,0" TextWrapping="Wrap" Text="{Binding PageTitle}"
d:LayoutOverrides="Width, Height" Style="{StaticResource PhoneTextLargeStyle}">
<Custom:Interaction.Triggers>
<Custom:EventTrigger EventName="MouseLeftButtonDown">
<GalaSoft_MvvmLight_Command:EventToCommand Command="{Binding NavigateToPageCommand, Mode=OneWay}" CommandParameter="{Binding PageUri}"/>
</Custom:EventTrigger>
</Custom:Interaction.Triggers>
</TextBlock>
</Grid>
</DataTemplate>


The EventToCommand behavior is dragged from the Assets | Behaviors section and is dropped on the TextBlock. Figure 2 shows the Properties window for the EventToCommand behavior.

Figure 2. EventToCommand properties in Expression Blend

In Figure 6-2, the Command value is databound to the NavigateToPageCommand property on the PageItemViewModel class. The CommandParameter is databound to PageUri property of the selected item from the MainViewModel Pages collection of type PageItemViewModel.

This was a detailed walkthrough of relatively simple functionality, but it demonstrates the powerful capabilities of MVVM Light's Commanding and Messaging infrastructure to support decoupling UI from the ViewModel via Silverlight's data binding framework.

Other  
  •  Beginning Android 3 : The Input Method Framework - Fitting In
  •  Mobile Application Security : Mobile Geolocation - Geolocation Methods & Geolocation Implementation
  •  Mobile Application Security : SMS Security - Application Attacks & Walkthroughs
  •  iPad SDK : Popovers - The Stroke Width Popover
  •  iPad SDK : Popovers - The Font Size Popover
  •  Beginning Android 3 : The Input Method Framework - Tailored to Your Needs
  •  Beginning Android 3 : Working with Containers - Scrollwork
  •  Mobile Application Security : SMS Security - Protocol Attacks (part 2)
  •  Mobile Application Security : SMS Security - Protocol Attacks (part 1)
  •  Mobile Application Security : SMS Security - Overview of Short Message Service
  •  iPad SDK : Popovers - The Font Name Popover (part 2)
  •  iPad SDK : Popovers - The Font Name Popover (part 1)
  •  Beginning Android 3 : Working with Containers - Tabula Rasa
  •  Beginning Android 3 : Working with Containers - LinearLayout Example & The Box Model
  •  iPhone Application Development : Reading and Writing User Defaults (part 2) - Implementing System Settings
  •  iPhone Application Development : Reading and Writing User Defaults (part 1) - Creating Implicit Preferences
  •  - Mobile Application Security : SMS Security - Overview of Short Message Service
  •  - Mobile Application Security : Bluetooth Security - Bluetooth Security Features
  •  Integrating Your Application with Windows Phone 7
  •  Introducing Windows Phone 7 Photo Features (part 2) - Using a Chooser to Open Photos & Saving Photos to the Phone
  •  
    Top 10
    Nikon 1 J2 With Stylish Design And Dependable Image And Video Quality
    Canon Powershot D20 - Super-Durable Waterproof Camera
    Fujifilm Finepix F800EXR – Another Excellent EXR
    Sony NEX-6 – The Best Compact Camera
    Teufel Cubycon 2 – An Excellent All-In-One For Films
    Dell S2740L - A Beautifully Crafted 27-inch IPS Monitor
    Philips 55PFL6007T With Fantastic Picture Quality
    Philips Gioco 278G4 – An Excellent 27-inch Screen
    Sony VPL-HW50ES – Sony’s Best Home Cinema Projector
    Windows Vista : Installing and Running Applications - Launching Applications
    Most View
    Bamboo Splash - Powerful Specs And Friendly Interface
    Powered By Windows (Part 2) - Toshiba Satellite U840 Series, Philips E248C3 MODA Lightframe Monitor & HP Envy Spectre 14
    MSI X79A-GD65 8D - Power without the Cost
    Canon EOS M With Wonderful Touchscreen Interface (Part 1)
    Windows Server 2003 : Building an Active Directory Structure (part 1) - The First Domain
    Personalize Your iPhone Case
    Speed ​​up browsing with a faster DNS
    Using and Configuring Public Folder Sharing
    Extending the Real-Time Communications Functionality of Exchange Server 2007 : Installing OCS 2007 (part 1)
    Google, privacy & you (Part 1)
    iPhone Application Development : Making Multivalue Choices with Pickers - Understanding Pickers
    Microsoft Surface With Windows RT - Truly A Unique Tablet
    Network Configuration & Troubleshooting (Part 1)
    Panasonic Lumix GH3 – The Fastest Touchscreen-Camera (Part 2)
    Programming Microsoft SQL Server 2005 : FOR XML Commands (part 3) - OPENXML Enhancements in SQL Server 2005
    Exchange Server 2010 : Track Exchange Performance (part 2) - Test the Performance Limitations in a Lab
    Extra Network Hardware Round-Up (Part 2) - NAS Drives, Media Center Extenders & Games Consoles
    Windows Server 2003 : Planning a Host Name Resolution Strategy - Understanding Name Resolution Requirements
    Google’s Data Liberation Front (Part 2)
    Datacolor SpyderLensCal (Part 1)