Mvvm reconstruction record on WP7 client of Douban station using message of mvvm light for navigation

Source: Internet
Author: User

Using mvvm to reconstruct this application over the past few days, we found a serious problem, that is, navigation. Based on the mvvm idea, the view and viewmodel communicate with each other by binding technology. In addition, the view can get the viewmodel and the viewmodel cannot get the view. It was easy to navigate when codebehind was used, and there was no way to do it here. Of course, there is also a way to pass the view to the viewmodel, but this damages the original intention of mvvm.

To solve this problem, we first need to solve how to obtain navgationservices in viewmodel for navigation. The solution is as follows:

 
Root =Application. Current. rootvisualAsPhoneapplicationframe;

After getting this root, you can navigate.

 
Root. navigate (pageuri); however, navigation directly in viewmodel always feels abrupt, and there is an important problem, that is, when codebehind is used, you can rewrite onnavigatedto and other methods to process the logic in viewmodel. After learning about the message mechanism of mvvm light, I thought of a solution.
 
The message mechanism of mvvm light can send a message, which is broadcasted, received by the register object, and then called the specified method.
 
Ideas:
When a VM needs to navigate, send a message to pass out the navigation URL. The message is intercepted by a navgationcontroller and the navigation operation is executed. After the navigation is complete, navgationcontroller sends a message, the viewmodel corresponding to the view to which the notification is navigated executes the navigated method.
 
 
 
Navigationhelper:
 
 
 Using System; Using System. Collections. Generic; Using System. windows; Using Microsoft. Phone. controls; Using Galasoft. mvvmlight. messaging; Namespace Mvvmlightnavgation { Public class Navigationhelper { Private Static  Phoneapplicationframe Root; Public static phoneapplicationframe Getphoneframeroot (){
If(Root =Null) {Root =Application. Current. rootvisualAsPhoneapplicationframe;If(Root =Null){Throw newException("An error occurred while obtaining applicationrootvisual! ");}}
 
Return root;

}
/// <Summary>
///Navigation by URL string
/// </Summary>
/// <Param name = "url"> </param>
Public static voidNavigationto (StringURL)
{
If(Root =Null)
Getphoneframeroot ();

If(Root! =Null)
{
VaRPageuri =NewUri(URL,Urikind. Relative );
Root. navigate (pageuri );
}

}

///


/// navigate by Uri
///
///
Public static void navigationto ( URI pageuri)
{< br> If (root = null )
getphoneframeroot ();

If(Root! =Null)
{
Root. navigate (pageuri );
}
}
Public staticUriCreateuri (StringURL)
{
Return newUri(URL,Urikind. Relativeorabsolute );
}

/// <Summary>
/// Send navigation msg
/// </Summary>
/// <Param name = "pageuri"> </param>
Public static void Navigationmsgsend ( Uri Pageuri)
{
Messenger . Default. Send (pageuri, Msgtoken . Navigation );
}
/// <Summary>
/// Send navigation msg
/// </Summary>
/// <Param name = "pageurl"> </param>
Public static void Navigationmsgsend ( String Pageurl)
{
Messenger . Default. Send (createuri (pageurl ),Msgtoken . Navigation );
}

/// <Summary>
///Registered navigation complete msg
/// </Summary>
Public static voidNavigatedmsgreg (ObjectRecipient)
{
InavigationNavigation = recipientAsInavigation;
If(Navigation! =Null)
{
Messenger. Default. register <Uri> (Recipient, navigation. getviewurl (), navigation. navigated );
}
}
}
}

This class provides a bunch of static methods to implement navigation between pages. The most important method is:

 
/// <Summary> ///Send navigation msg/// </Summary> /// <Param name = "pageurl"> </param>Public static voidNavigationmsgsend (StringPageurl ){Messenger. Default. Send (createuri (pageurl ),Msgtoken. Navigation);} This method will send a navigation message, which will be intercepted by the navigation controller.
/// <Summary> ///Registered navigation complete msg/// </Summary>Public static voidNavigatedmsgreg (ObjectRecipient ){InavigationNavigation = recipientAsInavigation;If(Navigation! =Null){Messenger. Default. register <Uri> (Recipient, navigation. getviewurl (), navigation. navigated );}}
 
This method registers an acceptance object and method for the navigation, and intercepts the completion message sent by the navigation controller.
 
 
 

Navigationcontroller:

 Using Galasoft. mvvmlight. messaging; Namespace Mvvmlightnavgation { Public class  Navigationcontroller { Public Navigationcontroller (){ Messenger . Default. register < Uri > ( This , Msgtoken . Navigation, navigation );
  navigationhelper . getphoneframeroot (). navigated + =  New  system. windows. navigation.  navigatedeventhandler  (rootnavigated);}  private void  navigation ( URI  URI) { navigationhelper . navigationto (URI) ;}
Private voidRootnavigated (ObjectSender, system. Windows. navigation.NavigationeventargsE ){StringToken = E. Uri. originalstring;If(Token. Contains ("? ")){IntIndex = E. Uri. originalstring. indexof ('? '); Token = token. substring (0, index );}Messenger. Default. Send (E. Uri, token );}
 
This method is the callback method after the navigation is complete. It sends a message with the URL corresponding to the navigation view as the token.
 
}}

The navigation controller intercepts all navigation messages and then navigating. After the navigation is complete, the VM corresponding to the view to which the Message notification navigation is sent executes the navigated method.

 

Navigation interface:

 
NamespaceMvvmlightnavgation {Public interfaceInavigation{/// <Summary> ///Get the URL of the corresponding View/// </Summary> /// <returns> </returns>StringGetviewurl ();/// <Summary> ///When navigation is complete/// </Summary> /// <Param name = "Uri"> </param>VoidNavigated (UriUri) ;}} let the VM implement this interface to ensure that all VMS have these two methods.
 
 

Usage:

AddNavigationcontrollerStatic Resources

   <  Application. Resources  > <  VM  :  Mvvmviewmodellocator  Xmlns  :  VM  = "CLR-namespace: dbfm7"  X  :  Key  = "Locator"/> <  NAV :  Navigationcontroller  X  :  Key  = "Navctr"/> </  Application. Resources  > 

Send a navigation message where you want to navigate:

 
StringPageurl ="/View/mainpage. XAML? Channle ="+ Hubtitle;Navigationhelper. Navigationmsgsend (pageurl); register an object in the VM constructor that receives the navigation completion message.
 
PublicChanneltileviewmodel (){
Navigationhelper. Navigatedmsgreg (This);

}

VM to implement the navigation interface:

 
Public classChanneltileviewmodel:Viewmodelbase,Inavigation{
 
...................
/// <Summary> ///When navigation is complete/// </Summary> /// <Param name = "Uri"> </param>Public voidNavigated (UriUri ){}/// <Summary> ///Get the URL of the corresponding View/// </Summary> /// <returns> </returns>Public StringGetviewurl (){Return"/View/channeltile. XAML";}}
 
The transition between message and navigationcontroller completely solves the coupling problem between view and viewmodel caused by navigation. In addition, it can easily extend the logic of navigating, navigatefailed, and navigatestopped.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.