Windows Phone From Scratch #20
MVVM Light Toolkit Soup To Nuts #5
In the previous posting in this series, we created a list of customers and we bound them to a list box. We did this not in the code-behind but in the View-Model. This forces the question of how we respond when a user makes a selection in the list box, if the logic for handling the selection is to be not in the view (the code-behind) but in the view-model.
The answer will not be overly surprising to anyone who has been following this series; we’ll use a behavior to capture the selected value and pass the selection to the view model class. The trick here is to use RelayCommand<T> rather than a simple RelayCommand.
Taking this step by step, please re-open the project and create a new MVVMLight View named Details. Also add a new MVVMLight View-Model named DetailsViewModel. Wire them together as explained in Part 1.
Now, taking the lesson from Part 2, open MainViewModel.cs and add a property for the command (this will be bound to by the behavior)
public RelayCommand<Customer> DetailsPageCommand { get; private set; }
Note the type, which is RelayCommand<Customer> indicating that this command will take a parameter of type Customer (hint: it will be the selected item in the list box).
In the constructor initialize the RelayCommand:
DetailsPageCommand = new RelayCommand<Customer>( ( msg ) => GoToDetailsPage( msg ) );
Note here that msg is the Customer being passed as a parameter from the behavior to the implementing method.
Finally, implement the GoToDetailsPage method, passing along the parameter. Normally, this method would be responsible for actually navigating to the Details page and showing the customer details, but to simplify, we can have it just display a message box with the information received,
private object GoToDetailsPage( Customer msg ) { System.Windows.MessageBox.Show( "Go to details page with: " + msg.First + " " + msg.Last ); return null; }
Complete source is available here.
If I wanted to pass IN the message to the other site the CustomerCollection list ( as in to not have to create a new instance of that class ) with the selected Customer how would I do that?
The solution to my problem can be found here: http://blogs.xamlninja.com/xaml/wp7-contrib-the-last-messenger
public class Page2ViewModel : ViewModelBase
{
private Customer _Customer;
public Customer Customer
{
get { return _Customer; }
set { _Customer = value; }
}
public string ApplicationTitle
{
get { return PhoneHelper.GetAppAttribute(“Title”); }
}
public string PageName
{
get
{
return “Page 2”;
}
}
public string CustomerName
{
get
{
return string.Format(“Selected: {0} {1}”, Customer.First, Customer.Last);
}
}
public Page2ViewModel()
{
Messenger.Default.Register(this, (cust) => ReceiveMessage(cust));
}
public void ReceiveMessage(Customer cust)
{
Customer = cust;
}
}
Page2View.xaml :
<TextBlock Text="{Binding CustomerName}"
MainViewModel:
public MainViewModel()
{
DetailsPageCommand = new RelayCommand((cust) => GoToDetailsPage(cust));
private object GoToDetailsPage(Customer cust)
{
Messenger.Default.Send(cust);
return null;
}
My problem is that the first time page2 is shown CustomerName is called from the TextBlock before ReceiveMessage is hit where the selected customer item is setup.
What should I have done?
@Richie Scott
I am also interested to see how Jesse does it. I was able to display the detailsView by using the galasoft MVVM light package. The view model for the detailsView instantiates a Relaycommand using the selectedItem from the MainView list box as a parameter. This can be done in Expression Blend very easily from the MainView page using both the NavigateToPageAction and EventToCommand behaviors. Of course you have to design the view model correctly. It works fine for me. To navigate back to the MainView, I used a NavigateToPageAction from the detailsView content grid based on the MouseUp event.
Jesse what a great series this is. However in this post I’m finding it hard to realise how you intend to show the details page with the correct datacontext (i.e. selected item). Are there 2 messages that are being sent when the relay command is executed…one to navigate to the new page and one to update the viewmodel with the correct customer. Or 1 message with the viewmodel being updated automagically on navigation to the page?
Hopefully your next post will tell us.
Thanks
Thanks Jesse for all of your tutorials. They are a tremendous help to me as I learn more about Silverlight and MVVM. I have already taken this Tutorial to the next level and am able to display the Detals page using your techniques. I have been trying to move to the next step ahead of your posts just to test my abilities. It will be interesting to see how close I can get to your solution.
I think a better example would be one where the SelectedItem is NOT passed as a command parameter (although it would defeat the purpose of this tutorial). This is because the SelectedItem should have a TwoWay binding with the ViewModel so the ViewModel is already completely aware of the selected customer (no need to pass it as a parameter).
I’d like to see that example, I was just wondering how the model should set the selected item. If a settings screen was loading data from a store for example.
Jesse, I think you have left out one important detail in the post, how to connect the dots between the Listbox selected item and the RelayCommand:
Of course, this is actually in the downloadable source code, but it could have been pointed out in the tutorial.
Regards,
Magnus