Sunday, September 26, 2010

Silverlight client for REST using MVVM

In my previous post I talked about MVVM model. Here I will demonstrate a very simple implementation of MVVM model to create a Silverlight client for consuming REST Service.

The application is a netflix catalog using MVVM model and it is based on this sample.

The Application has 3 project

1. Silverlight UI containing the View and the ViewModel.
2. Silverlight dll project containing the Business Model or the Model.
3. Web project containing the page to host the Silverlight application.

I'll start from implementing the Model.

1st of all we need to know our DataModel, which in our case would be created by adding a service reference to the http://odata.netflix.com/catalog

If you are using Visual Studio 2010, you may create a new Silverlight library project called Model and Add a Service reference pointing to http://odata.netflix.com/catalog


On successful creation of ServiceRefrence, the service.edmx file will be generated along with the Reference. these files will be hidden by default. You've to click on "Show All Files" to view them. This will be our DataModel

After adding the ServiceRefrence successfully, we may proceed to add the Business Model or Model and name it CatalogModel.

CatalogModel will have to implement the INotificationChanged interface to notify any change in property.

public class CatalogModel:INotifyPropertyChanged

        #region INotify implementation
        public event PropertyChangedEventHandler PropertyChanged;

        private void raisePropertryChanged(string propertyName)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
            }
        }
        #endregion
        private Visibility _isLoadingGenres = Visibility.Visible;
        public Visibility IsLoadingGenres
        {
            get { return _isLoadingGenres; }
            set
            {
                _isLoadingGenres = value;
                raisePropertryChanged("IsLoadingGenres");
            }
        }

        private Visibility _isLoadingTitles;
        public Visibility IsLoadingTitles
        {
            get { return _isLoadingTitles; }
            set
            {
                _isLoadingTitles = value;
                raisePropertryChanged("IsLoadingTitles");
            }
        }
public DataServiceCollection<Genre> Genres { get; set; }
        private Genre _selectedGenre;
        public Genre SelectedGenre
        {
            get
            {
                return _selectedGenre;
            }
            set
            {
                if (value != _selectedGenre)
                {
                    _selectedGenre = value;
                    _selectedGenre.Titles.LoadCompleted += (s, e) =>
                        {
                            IsLoadingTitles = Visibility.Collapsed;
                        };
                    _selectedGenre.Titles.LoadAsync();
                    IsLoadingTitles = Visibility.Visible;
                    raisePropertryChanged("SelectedGenre");
                }
            }
        }
        public CatalogModel()
        {
            NetflixCatalog _context = new NetflixCatalog(new Uri("http://odata.netflix.com/Catalog/"));
            Genres = new DataServiceCollection<Genre>();
            var query = (from g in _context.Genres
                         orderby
                             g.Name
                         select g);
            Genres.LoadCompleted += (s, e) =>
                {
                    IsLoadingGenres = Visibility.Collapsed;
                };
            Genres.LoadAsync(query);
            IsLoadingGenres = Visibility.Visible;
        }
 }

Now we will create our ViewModel. Go to your Silverlight UI project and add a new class called ViewModel;
public class ViewModel:INotifyPropertyChanged
    {
        private CatalogModel _model = new CatalogModel();
        public CatalogModel Model
        {
            get
            {
                return _model;
            }
            set
            {
                _model = value;
                raisePropertryChanged("Model");
            }
        }

        #region INotify implementation
        public event PropertyChangedEventHandler PropertyChanged;

        private void raisePropertryChanged(string propertyName)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
            }
        }
        #endregion

Now we will construct the View, that is the XAML:

<Grid x:Name="LayoutRoot" Background="White" Width="360" Margin="20">
        <Grid.Resources>
            <local:ViewModel x:Name="MainPageViewModel"/>
        </Grid.Resources>
        <StackPanel DataContext="{StaticResource MainPageViewModel}" >
            <StackPanel Orientation="Horizontal" HorizontalAlignment="Center">
                <TextBlock Text="Select Genere" VerticalAlignment="Center" HorizontalAlignment="Right" Margin="0,0,5,0"  />
                <ComboBox Name="GenreCombobox" ItemsSource="{Binding Model.Genres}" SelectedItem="{Binding Model.SelectedGenre, Mode=TwoWay}"  DisplayMemberPath="Name" VerticalAlignment="Center" HorizontalAlignment="Left" MinWidth="150" />
                <TextBlock Text="Loading..."  Visibility="{Binding Model.IsLoadingGenres}" Margin="-140,0,0,0"/>
            </StackPanel>
            <ListBox Name="CatalogTitleListBox" DataContext="{Binding Model.SelectedGenre}" ItemsSource="{Binding Titles}" Margin="0,5" Height="535" >
                <ListBox.ItemTemplate>
                    <DataTemplate>
                        <StackPanel Orientation="Horizontal">
                            <Image Source="{Binding BoxArt.MediumUrl}"  />
                            <StackPanel Orientation="Vertical">
                                <TextBlock Text="{Binding Name}" FontSize="14" FontFamily="Lucida Sans Unicode" FontWeight="Bold"></TextBlock>
                                <StackPanel Orientation="Horizontal">
                                    <TextBlock>Rated:</TextBlock>
                                    <TextBlock Text="{Binding Rating}" FontSize="12" FontFamily="Lucida Sans Unicode"></TextBlock>
                                </StackPanel>
                                <StackPanel Orientation="Horizontal">
                                    <TextBlock>Release Year:</TextBlock>
                                    <TextBlock Text="{Binding ReleaseYear}" FontSize="12" FontFamily="Lucida Sans Unicode"></TextBlock>
                                </StackPanel>
                                <StackPanel Orientation="Horizontal">
                                    <TextBlock>Average User Rating:</TextBlock>
                                    <TextBlock Text="{Binding AverageRating}"></TextBlock>
                                    <TextBlock> /5</TextBlock>
                                </StackPanel>
                                <StackPanel Orientation="Horizontal">
                                    <TextBlock>I've seen it</TextBlock>
                                    <CheckBox IsChecked="{Binding Seen}"/>
                                </StackPanel>
                            </StackPanel>
                        </StackPanel>
                    </DataTemplate>
                </ListBox.ItemTemplate>
            </ListBox>
        </StackPanel>
    </Grid>

There is 0 lines of code in the code behind file of xaml.cs

This was a very simple implementation of MVVM model.

No comments:

Post a Comment