Creating your first MVVM silverlight application on windows phone 7.

by Rod
5. June 2010 15:13

The goal of this tutorial is to create an MVVM driven twitter mini client application for windows phone 7. We’ll do the exact same twitter client Scott Guthrie did in the MIX 10 presentation except we’ll follow the MVVM pattern. 
So here’s how we’d want it to look like.

The source code for this tutorial is also available.

1) Why MVVM ?

MVVM is a design pattern, better for testing and for big enterprise projects since there wouldn’t be any code behind in your view, everything would be exposed and controlled by your ViewModel – so easier to test.
(Here’s a more detailed guide about the MVVM pattern).

Here’s a schema summarizing the pattern:

MVVM_pattern_diagram_thumb

2) In order to develop for Windows Phone 7, you need to get the free SDK here, the current version is the April CTP refresh. (Visual Studio 2010 Express comes with the tools you can download, so developing for windows phone 7 can be absolutely free).

Let’s Start coding!

Open Visual Studio and create a new project using the “Silverlight for Windows Phone” Tab and choosing the “Windows Phone Application” template.

Let’s start of by creating a new class called: ViewModelBase and make it implement the INotifyPropertyInterface.

This is going to be the class we’re going to derive from all of our ViewModels.

Now let’s add some properties in this Base class in order to get save some lines of code and not repeat ourselves in the other ViewModel classes we’re going to write.

protected void OnNotifyPropertyChanged(string p)
{
    if (PropertyChanged != null)
    {
        PropertyChanged(this, new PropertyChangedEventArgs(p));
    }
}       
public event PropertyChangedEventHandler PropertyChanged;

This basically says whenever my property is changed the event PropertyChanged is launched.

Let’s create our View now.

Open up the MainPage.xaml.

I’m going to add a TextBox, a button and a listbox unto the design view (you can manipulate the controls and dimension them to whatever you want from the designer view etc ..)

So here’s how my view looks like right now:

view

Now let’s modify our listbox in order to contain an image and the status update. (many ways you can do this, you can ofcourse do it from Blend), but this isn’t the purpose of this tutorial. So we’ll keep it simple.

Add a Image then a textbox for the message and another for the username inside the listbox template while editing the xaml.

So our Xaml for the listbox can look like this:

  <ListBox Height="500" HorizontalAlignment="Left" 
                     Margin="20,115,0,0" 
                     Name="listBox1" VerticalAlignment="Top" Width="440">
                <ListBox.ItemTemplate>
                    <DataTemplate>
                        <StackPanel Orientation="Horizontal">
                            <Image Height="100" Width="100" 
                                   VerticalAlignment="Top" Margin="0,10,8,0"/>
                            <StackPanel Orientation="Vertical">
                                <TextBlock />
                                <TextBlock   />
                            </StackPanel>
                        </StackPanel>
                    </DataTemplate>
                </ListBox.ItemTemplate>
            </ListBox>

 

Now let’s add our ViewModel for this specific View.

Create a new folder called “ViewModels” and then a new class in that folder named: “MainViewModel”

Make that class derive from our “ViewModelBase” class.

So let’s think about what we want exactly:

* When the button Look up is pressed we want the above page title to change to “Whatever we put in the textbox” ‘s Feed”.

* When the button Look up is pressed, we get the status updates for the specific user entered in the textbox.

Okay let’s jump into that, remember there shouldn’t be any code behind on my view that’s event driven specific etc..

First let’s start off by linking our View to the ViewModel we just created.

There are two ways of doing this, one from the View XAML directly, the other in the code behind while calling the constructor of the View.

The most common method is the second so we’ll do that.

Open the code behind of the MainPage View.

Add the namespace of the ViewModels, create a new variable of type “MainViewModel”.
Set the DataContext of the View as the MainViewModel variable we just created.

private MainViewModel _mainViewModel = new MainViewModel();

        public MainPage()
        {
            InitializeComponent();
            DataContext = _mainViewModel;
        }

 

Here’s the inside of our MainPage class now.

Let’s create now our TwitterItem class:

Create a new class called TwitterItem and add the following properties (there’s nothing different here from ScottGu’s post) : Username , Message, ImageSource.

Then add a static method that we’ll help us parse the xml returned and return a list of TwitterItems.

So overall our class looks like this now:

public class TwitterItem
{
    public string Username { get; set; }
    public string Message { get; set; }
    public string ImageSource { get; set; }

    public static List<TwitterItem> GetTweetsFromResponse(String Response)
    {
        List<TwitterItem> lsttweets = new List<TwitterItem>();

        XElement xmlTweets = XElement.Parse(Response);
        lsttweets = (from tweet in xmlTweets.Descendants("status")
                    select new TwitterItem
                    {
                        ImageSource = tweet.Element("user").Element("profile_image_url").Value,
                        Message = tweet.Element("text").Value,
                        Username = tweet.Element("user").Element("screen_name").Value
                    }).ToList();

        return lsttweets;
    }
}


Now let’s go back to our MainViewModel class.

I’m going to need a property for the textbox text (which will be the username for the feeds we want to get), another one for the title, and finally a RelayCommand for the Button.

What? RelayCommand? what’s that? it’s a helper from the MVVM light toolkit developed by Laurent Bugnion
(He also presented the Toolkit in MIX 10)

The toolkit works on WPF, Silverlight and WP7.

Now why would we need this?It’s simply a really big time saver + commands don’t exist on WP7 because WP7 use Silverlight 3.

RelayCommands helps us link commands on methods, you’ll understand this in a minute.

So first let’s add the dlls from the toolkit you can get them here.

references

Now that’s done we can add our RelayCommand.

So this how class looks like now:

public class MainViewModel : ViewModelBase
    {
        public string strUsername { get; set; }
        public RelayCommand GetTweetsCommand { get; private set; }
    }

 

Now we need an ObservableCollection for the tweets, and this collection will be the item source of our listbox.

private ObservableCollection<TwitterItem> _lstTweets;
public ObservableCollection<TwitterItem> LstTweets
{
    get
    {
        return _lstTweets;
    }
    set
    {
        if (_lstTweets != value)
        {
            _lstTweets = value;
            OnNotifyPropertyChanged("LstTweets");
        }
    }
}

Finally our last property needed, is the Title one since it’s going to be binded to the title in order to set the Title to “screen name” ‘s feed.

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


Now let’s write the methods to get the tweets from the twitter api (one will be used for the async call,
and the other for the response):

private void GetTweetsCall(string screenName)
  {
      WebClient client = new WebClient();
      client.DownloadStringCompleted += 
          new DownloadStringCompletedEventHandler(twitter_Response);
      client.DownloadStringAsync(
          new Uri("http://api.twitter.com/1/statuses/user_timeline.xml?screen_name="
              + screenName));
  }

  private void twitter_Response(object sender, DownloadStringCompletedEventArgs e)
  {
     if (e.Error == null)
      {
          LstTweets = TwitterItem.GetTweetsFromResponse(e.Result);
      }
  }

 

Finally we have to add the constructor and in that constructor we’re going to link our relay command to the method that calls the twitter api, and set the “Title” property with the txtUsername property + “’s feed”:

public MainViewModel()
 {
         GetTweetsCommand = new RelayCommand(() =>
             {
                 Title = txtUsername + "'s Feeds";
                 GetTweetsCall(txtUsername);
             }
         );
 }


All this is nice, but that’s not enough, we need to bind everything on the View.

So for the title TextBlock, we bind the text to the Title:

<TextBlock Text="{Binding Title, Mode=OneWay}" 
                       Style="{StaticResource PhoneTextPageTitle2Style}"/>

 

Repeat the same thing for the TextBox but instead of setting the Mode OneWay you have to set it TwoWay because we’re using the Text written in the TextBox by the user in our ViewModel.

<TextBox Height="72" HorizontalAlignment="Left" Margin="31,37,0,0" 
                     Text="{Binding txtUsername,Mode=TwoWay}" 
                     VerticalAlignment="Top" Width="275" />

Now we have to bind the listbox Item source to our ObservableCollection.

  <ListBox Height="500" HorizontalAlignment="Left" 
                     Margin="20,115,0,0" 
                     VerticalAlignment="Top" 
                     Width="440" ItemsSource="{Binding LstTweets, Mode=OneWay}">

So what’s left? Binding the image and 2 textblocks inside our listbox.

   <Image Height="100" Width="100"  Source="{Binding ImageSource , Mode=OneWay}"
                                   VerticalAlignment="Top" Margin="0,10,8,0"/>
                            <StackPanel Orientation="Vertical">
                                <TextBlock  Text="{Binding Username , Mode=OneWay}"  />
                                <TextBlock  Text="{Binding Message , Mode=OneWay}"  
                                           />
                            </StackPanel>


Now how do we set the Command on our button in wp7 based on Silverlight 3 where commands weren't supported ?  With the MVVM light toolkit!

It’s easier to do this with Blend by just drag and dropping , but not the purpose of this tutorial ;) ..

So just copy/paste this in your button XAML:

  <Button Content="Look up" Height="70" 
                    HorizontalAlignment="Left" Margin="300,37,0,0" 
                    VerticalAlignment="Top" Width="160">
                <i:Interaction.Triggers>
                    <i:EventTrigger EventName="Click">
                        <GalaSoft_MvvmLight_Command:EventToCommand 
                            Command="{Binding GetTweetsCommand, Mode=OneWay}"/>
                    </i:EventTrigger>
                </i:Interaction.Triggers>
            </Button>

Add the necessary namespace imports :

 xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity" 
 xmlns:GalaSoft_MvvmLight_Command="clr-namespace:GalaSoft.MvvmLight.Command;assembly=GalaSoft.MvvmLight.Extras.WP7" 
  

As you noticed the Command Binding in the eventTrigger is set to the RelayCommand we created in our ViewModel.

Then a little bit of styling on our View in order to make it look good.

Run your application now!

Type in a screen name inside the textbox and click the “Look up” button and this is the result:

result


Hope you enjoyed this article, MVVM isn’t an easy concept, but a lot of helpers out there, I personally really like MVVM light toolkit. I'll do my best to write more articles on windows phone 7 and MVVM!

In the mean time you can get the source code here.

Tags: , ,

WP7

Comments

6/5/2010 8:01:27 PM #

Laurent Bugnion

Hi,

Nice article. One comment: It is not necessary to use EventToCommand to set a Command on a Button for the Click event. This is possible, but it adds a dependency on GalaSoft.MvvmLight.Extras and on System.Windows.Interactivity. Instead, you can just remove these two dependencies and use the ButtonBaseExtension class, for example:

<Button cmd:ButtonBaseExtension.Command="{Binding MyCommand}"
    cmd:ButtonBaseExtension.CommandParameter="Something"
    Content="Hello world" />

with xmlns:cmd="clr-namespace:GalaSoft.MvvmLight.Command;assembly=GalaSoft.MvvmLight.SL4"

This syntax is easier to remember and does not need the additional DLLs. EventToCommand, on the other hand, is needed to handle other events on the Button class or any event on any other UIElement.

Cheers,
Laurent

Laurent Bugnion Switzerland | Reply

6/5/2010 8:21:51 PM #

pingback

Pingback from topsy.com

Twitter Trackbacks for
        
        Choose your career, Choose your future, Choose .NET | Creating your first MVVM silverlight application on windows phone 7.
        [rodrigueh.com]
        on Topsy.com

topsy.com | Reply

7/28/2010 12:28:43 AM #

trackback

Comparing WP7 development to BlackBerry

Comparing WP7 development to BlackBerry

Choose your career, Choose your future, Choose .NET | Reply

Add comment


(Will show your Gravatar icon)

  Country flag

biuquote
  • Comment
  • Preview
Loading



About the author

Rodrigue Hajjar

.NET Developer.

.Supinfo Student.

 

Calendar

<<  September 2010  >>
MoTuWeThFrSaSu
303112345
6789101112
13141516171819
20212223242526
27282930123
45678910

View posts in large calendar