<?xml version="1.0" encoding="utf-8" ?>
<?xml-stylesheet type="text/xsl" href="RSS_xslt_style.asp" version="1.0" ?>
<rss version="2.0" xmlns:WebWizForums="http://syndication.webwiz.co.uk/rss_namespace/">
 <channel>
  <title>DevForce Community Forum : Digging Deeper!</title>
  <link>http://www.ideablade.com/forum/</link>
  <description>This is an XML content feed of; DevForce Community Forum : DevForce 2009 : Digging Deeper!</description>
  <pubDate>Tue, 28 Apr 2026 08:07:17 -700</pubDate>
  <lastBuildDate>Thu, 23 Apr 2009 02:24:18 -700</lastBuildDate>
  <docs>http://blogs.law.harvard.edu/tech/rss</docs>
  <generator>Web Wiz Forums 9.69</generator>
  <ttl>360</ttl>
  <WebWizForums:feedURL>www.ideablade.com/forum/RSS_post_feed.asp?TID=1229</WebWizForums:feedURL>
  <image>
   <title>DevForce Community Forum</title>
   <url>http://www.ideablade.com/forum/forum_images/IdeaBlade_logo_tm.png</url>
   <link>http://www.ideablade.com/forum/</link>
  </image>
  <item>
   <title>Digging Deeper! : Thanks Ben and Dom.   I think...</title>
   <link>http://www.ideablade.com/forum/forum_posts.asp?TID=1229&amp;PID=4441#4441</link>
   <description>
    <![CDATA[<strong>Author:</strong> <a href="http://www.ideablade.com/forum/member_profile.asp?PF=482" rel="nofollow">WardBell</a><br /><strong>Subject:</strong> 1229<br /><strong>Posted:</strong> 23-Apr-2009 at 2:24am<br /><br /><P style="MARGIN: 0in 1.5pt 0.75pt; LINE-HEIGHT: normal" ="Ms&#111;normal"><SPAN lang=EN style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: 'Verdana','sans-serif'; mso-fareast-font-family: 'Times New Roman'; mso-bidi-font-family: 'Times New Roman'; mso-ansi-: EN">Thanks Ben and Dom. <?: prefix = o ns = "urn:schemas-microsoft-com:office:office" /><O:P></O:P></SPAN></P><P style="MARGIN: 0.75pt 1.5pt; LINE-HEIGHT: normal" ="Ms&#111;normal"><SPAN lang=EN style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: 'Verdana','sans-serif'; mso-fareast-font-family: 'Times New Roman'; mso-bidi-font-family: 'Times New Roman'; mso-ansi-: EN">&nbsp;<O:P></O:P></SPAN></P><P style="MARGIN: 0.75pt 1.5pt; LINE-HEIGHT: normal" ="Ms&#111;normal"><SPAN lang=EN style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: 'Verdana','sans-serif'; mso-fareast-font-family: 'Times New Roman'; mso-bidi-font-family: 'Times New Roman'; mso-ansi-: EN">I think the issues / questions you both raise require more explication then a poor forum post can manager.<O:P></O:P></SPAN></P><P style="MARGIN: 0.75pt 1.5pt; LINE-HEIGHT: normal" ="Ms&#111;normal"><SPAN lang=EN style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: 'Verdana','sans-serif'; mso-fareast-font-family: 'Times New Roman'; mso-bidi-font-family: 'Times New Roman'; mso-ansi-: EN">&nbsp;<O:P></O:P></SPAN></P><P style="MARGIN: 0.75pt 1.5pt; LINE-HEIGHT: normal" ="Ms&#111;normal"><SPAN lang=EN style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: 'Verdana','sans-serif'; mso-fareast-font-family: 'Times New Roman'; mso-bidi-font-family: 'Times New Roman'; mso-ansi-: EN">I'm not sure how helpful this will be but I will try to answer Ben's questions BRIEFLY in hopes that my answer will hold the fort until I can express myself more expansively.<O:P></O:P></SPAN></P><P style="MARGIN: 0.75pt 1.5pt; LINE-HEIGHT: normal" ="Ms&#111;normal"><SPAN lang=EN style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: 'Verdana','sans-serif'; mso-fareast-font-family: 'Times New Roman'; mso-bidi-font-family: 'Times New Roman'; mso-ansi-: EN">&nbsp;<O:P></O:P></SPAN></P><P style="MARGIN: 0.75pt 1.5pt; LINE-HEIGHT: normal" ="Ms&#111;normal"><SPAN lang=EN style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: 'Verdana','sans-serif'; mso-fareast-font-family: 'Times New Roman'; mso-bidi-font-family: 'Times New Roman'; mso-ansi-: EN">First a caveat: the Model Explorer is not definitive on patterns or "best practices". The way we tackle MVVM and encapsulation of persistence operations is intended to be suggestive. But we had to sacrifice practices in order to keep M.E. small enough to be easily understood ... at least that was an important objective.<O:P></O:P></SPAN></P><P style="MARGIN: 0.75pt 1.5pt; LINE-HEIGHT: normal" ="Ms&#111;normal"><SPAN lang=EN style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: 'Verdana','sans-serif'; mso-fareast-font-family: 'Times New Roman'; mso-bidi-font-family: 'Times New Roman'; mso-ansi-: EN">&nbsp;<O:P></O:P></SPAN></P><P style="MARGIN: 0.75pt 1.5pt; LINE-HEIGHT: normal" ="Ms&#111;normal"><SPAN lang=EN style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: 'Verdana','sans-serif'; mso-fareast-font-family: 'Times New Roman'; mso-bidi-font-family: 'Times New Roman'; mso-ansi-: EN">Second, another caveat: no one has enough experience to say what the "best practices" really are. MVVM is itself a much debated pattern in its details; most everyone thinks it's the right approach but there are violent disagreements about the details.<O:P></O:P></SPAN></P><P style="MARGIN: 0.75pt 1.5pt; LINE-HEIGHT: normal" ="Ms&#111;normal"><SPAN lang=EN style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: 'Verdana','sans-serif'; mso-fareast-font-family: 'Times New Roman'; mso-bidi-font-family: 'Times New Roman'; mso-ansi-: EN">&nbsp;<O:P></O:P></SPAN></P><P style="MARGIN: 0.75pt 1.5pt; LINE-HEIGHT: normal" ="Ms&#111;normal"><SPAN lang=EN style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: 'Verdana','sans-serif'; mso-fareast-font-family: 'Times New Roman'; mso-bidi-font-family: 'Times New Roman'; mso-ansi-: EN">Ok ... onward.<O:P></O:P></SPAN></P><P style="MARGIN: 0.75pt 1.5pt; LINE-HEIGHT: normal" ="Ms&#111;normal"><SPAN lang=EN style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: 'Verdana','sans-serif'; mso-fareast-font-family: 'Times New Roman'; mso-bidi-font-family: 'Times New Roman'; mso-ansi-: EN">&nbsp;<O:P></O:P></SPAN></P><P style="MARGIN: 0.75pt 1.5pt; LINE-HEIGHT: normal" ="Ms&#111;normal"><B style="mso-bidi-font-weight: normal"><SPAN lang=EN style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: 'Verdana','sans-serif'; mso-fareast-font-family: 'Times New Roman'; mso-bidi-font-family: 'Times New Roman'; mso-ansi-: EN">ModelExplorerPersistenceService <O:P></O:P></SPAN></B></P><P style="MARGIN: 0.75pt 1.5pt; LINE-HEIGHT: normal" ="Ms&#111;normal"><SPAN lang=EN style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: 'Verdana','sans-serif'; mso-fareast-font-family: 'Times New Roman'; mso-bidi-font-family: 'Times New Roman'; mso-ansi-: EN"><O:P>&nbsp;</O:P></SPAN></P><P style="MARGIN: 0.75pt 1.5pt; LINE-HEIGHT: normal" ="Ms&#111;normal"><SPAN lang=EN style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: 'Verdana','sans-serif'; mso-fareast-font-family: 'Times New Roman'; mso-bidi-font-family: 'Times New Roman'; mso-ansi-: EN">The ModelExplorerPersistenceService is NOT part of the MVVM world. It a means of encapsulating persistence operations so that no other class has to know the intimate details of fetching and storing entities. We especially don't want our ViewModels doing that. They shouldn't be logging in or formulating queries or sorting out what went wrong if a save fails ... none of that.&nbsp; The PersistenceService is a </SPAN><B><I><SPAN lang=EN style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: 'Verdana','sans-serif'; mso-fareast-font-family: 'Times New Roman'; mso-bidi-font-family: 'Times New Roman'; mso-bidi-font-size: 11.0pt; mso-ansi-: EN">facade</SPAN></I></B><SPAN lang=EN style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: 'Verdana','sans-serif'; mso-fareast-font-family: 'Times New Roman'; mso-bidi-font-family: 'Times New Roman'; mso-ansi-: EN"> over whatever mechanism you choose to use (DevForce, RIA Services, your custom WCF solution) to manage the data.<O:P></O:P></SPAN></P><P style="MARGIN: 0.75pt 1.5pt; LINE-HEIGHT: normal" ="Ms&#111;normal"><SPAN lang=EN style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: 'Verdana','sans-serif'; mso-fareast-font-family: 'Times New Roman'; mso-bidi-font-family: 'Times New Roman'; mso-ansi-: EN">&nbsp;<O:P></O:P></SPAN></P><P style="MARGIN: 0.75pt 1.5pt; LINE-HEIGHT: normal" ="Ms&#111;normal"><SPAN lang=EN style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: 'Verdana','sans-serif'; mso-fareast-font-family: 'Times New Roman'; mso-bidi-font-family: 'Times New Roman'; mso-ansi-: EN">By the way, it is not a "Service" in the sense of a cross-process or cross-the-wire service; it is not SOA. It lives entirely on the client. It may invoke remote services in order to do its business but it is not itself a remote service. It is code that performs some activities for other components.<O:P></O:P></SPAN></P><P style="MARGIN: 0.75pt 1.5pt; LINE-HEIGHT: normal" ="Ms&#111;normal"><SPAN lang=EN style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: 'Verdana','sans-serif'; mso-fareast-font-family: 'Times New Roman'; mso-bidi-font-family: 'Times New Roman'; mso-ansi-: EN">&nbsp;<O:P></O:P></SPAN></P><P style="MARGIN: 0.75pt 1.5pt; LINE-HEIGHT: normal" ="Ms&#111;normal"><SPAN lang=EN style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: 'Verdana','sans-serif'; mso-fareast-font-family: 'Times New Roman'; mso-bidi-font-family: 'Times New Roman'; mso-ansi-: EN">What you will see is that ViewModels make use of PersistenceServices. In a world with Dependency Injection (DI), you will see such PersistenceServices injected into ViewModels. In this way, a ViewModel can acquire and save&nbsp;Model elements&nbsp;(the collective entities it needs such as Customer, Order, etc.) without becoming bogged down in the details of doing so.<O:P></O:P></SPAN></P><P style="MARGIN: 0.75pt 1.5pt; LINE-HEIGHT: normal" ="Ms&#111;normal"><SPAN lang=EN style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: 'Verdana','sans-serif'; mso-fareast-font-family: 'Times New Roman'; mso-bidi-font-family: 'Times New Roman'; mso-ansi-: EN">&nbsp;<O:P></O:P></SPAN></P><P style="MARGIN: 0.75pt 1.5pt; LINE-HEIGHT: normal" ="Ms&#111;normal"><SPAN lang=EN style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: 'Verdana','sans-serif'; mso-fareast-font-family: 'Times New Roman'; mso-bidi-font-family: 'Times New Roman'; mso-ansi-: EN">We felt that requiring DI for the Model Explorer in this incarnation would have been too offputting. So we explicitly pass a concrete PersistenceService into the ViewModel ... into the ModelExplorerViewModel in particular ... when we launch the app (see App.xaml.cs). See the line:<O:P></O:P></SPAN></P><P style="MARGIN: 0.75pt 1.5pt; LINE-HEIGHT: normal" ="Ms&#111;normal"><SPAN lang=EN style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: 'Verdana','sans-serif'; mso-fareast-font-family: 'Times New Roman'; mso-bidi-font-family: 'Times New Roman'; mso-ansi-: EN"><O:P>&nbsp;</O:P></SPAN></P><P style="MARGIN: 0.75pt 1.5pt 0.75pt 0.5in; LINE-HEIGHT: normal" ="Ms&#111;normal"><SPAN lang=EN style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: 'Courier New'; mso-fareast-font-family: 'Times New Roman'; mso-ansi-: EN">viewModel.ModelExplorerPersistenceService = <O:P></O:P></SPAN></P><P style="MARGIN: 0.75pt 1.5pt 0.75pt 0.5in; LINE-HEIGHT: normal" ="Ms&#111;normal"><SPAN lang=EN style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: 'Courier New'; mso-fareast-font-family: 'Times New Roman'; mso-ansi-: EN"><SPAN style="mso-spacerun: yes">&nbsp; </SPAN>new ModelExplorerPersistenceService();<O:P></O:P></SPAN></P><P style="MARGIN: 0.75pt 1.5pt; LINE-HEIGHT: normal" ="Ms&#111;normal"><SPAN lang=EN style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: 'Verdana','sans-serif'; mso-fareast-font-family: 'Times New Roman'; mso-bidi-font-family: 'Times New Roman'; mso-ansi-: EN"><O:P>&nbsp;</O:P></SPAN></P><P style="MARGIN: 0in 0in 10pt" ="Ms&#111;normal"><SPAN lang=EN style="FONT-SIZE: 9pt; COLOR: black; LINE-HEIGHT: 115%; FONT-FAMILY: 'Verdana','sans-serif'; mso-fareast-font-family: 'Times New Roman'; mso-bidi-font-family: 'Times New Roman'; mso-ansi-: EN">You should see substantial re-use of a PersistenceService, within one module. A “module” typically addresses a single, cohesive collection of tasks, each of which is a bundle of “use cases.” There are going to be many Views (many MVVMs) in a rich module. I think a PersistenceService should be oriented toward serving all of the needs of a module and, therefore, will be consumed by multiple ViewModels.<O:P></O:P></SPAN></P><P style="MARGIN: 0in 0in 10pt" ="Ms&#111;normal"><SPAN lang=EN style="FONT-SIZE: 9pt; COLOR: black; LINE-HEIGHT: 115%; FONT-FAMILY: 'Verdana','sans-serif'; mso-fareast-font-family: 'Times New Roman'; mso-bidi-font-family: 'Times New Roman'; mso-ansi-: EN">You might prefer in some situations to have more than one PersistenceService in a module. I’d think twice before I did this; it’s easy to get carried away and start creating too many fine-grained services ... at the cost of confusion and maintenance. <O:P></O:P></SPAN></P><P style="MARGIN: 0in 0in 10pt" ="Ms&#111;normal"><SPAN lang=EN style="FONT-SIZE: 9pt; COLOR: black; LINE-HEIGHT: 115%; FONT-FAMILY: 'Verdana','sans-serif'; mso-fareast-font-family: 'Times New Roman'; mso-bidi-font-family: 'Times New Roman'; mso-ansi-: EN">I realize that one big PersistenceService is a code smell too. Consider giving that PersistenceService multiple interfaces so that an individual ViewModel only depends upon the interface that meets its particular needs.<O:P></O:P></SPAN></P><P style="MARGIN: 0in 0in 10pt" ="Ms&#111;normal"><SPAN lang=EN style="FONT-SIZE: 9pt; COLOR: black; LINE-HEIGHT: 115%; FONT-FAMILY: 'Verdana','sans-serif'; mso-fareast-font-family: 'Times New Roman'; mso-bidi-font-family: 'Times New Roman'; mso-ansi-: EN">Sometimes you can use the same PersistenceService in multiple modules. I’d think twice about this too. Fortunately, M.E. is only a single module so we don’t have to think about this right now.<O:P></O:P></SPAN></P><P style="MARGIN: 0in 0in 10pt" ="Ms&#111;normal"><B style="mso-bidi-font-weight: normal"><SPAN style="FONT-SIZE: 9pt; LINE-HEIGHT: 115%; FONT-FAMILY: 'Verdana','sans-serif'">MVVM Actors<O:P></O:P></SPAN></B></P><P style="MARGIN: 0in 0in 10pt" ="Ms&#111;normal"><SPAN style="FONT-SIZE: 9pt; LINE-HEIGHT: 115%; FONT-FAMILY: 'Verdana','sans-serif'">In my view, “M”odel is made up of the entities that are ultimately exposed in the UI. We typically expose entity properties directly to the view by means of data binding. Most of us think that’s a fine idea most of the time.<O:P></O:P></SPAN></P><P style="MARGIN: 0in 0in 10pt" ="Ms&#111;normal"><SPAN style="FONT-SIZE: 9pt; LINE-HEIGHT: 115%; FONT-FAMILY: 'Verdana','sans-serif'">One of the jobs of the ViewModel is to acquire the entities that should be exposed and make them available to the View.<SPAN style="mso-spacerun: yes">&nbsp; </SPAN>We could just get them in the View’s code-behind … but that would be “bad” … for reasons I’ll not go into here.<O:P></O:P></SPAN></P><P style="MARGIN: 0in 0in 10pt" ="Ms&#111;normal"><SPAN style="FONT-SIZE: 9pt; LINE-HEIGHT: 115%; FONT-FAMILY: 'Verdana','sans-serif'">The ViewModel is also responsible for responding to user gestures such as button clicks. Again, we could put that handling logic in the View’s code-behind … but that would be “bad” too.<O:P></O:P></SPAN></P><P style="MARGIN: 0in 0in 10pt" ="Ms&#111;normal"><SPAN style="FONT-SIZE: 9pt; LINE-HEIGHT: 115%; FONT-FAMILY: 'Verdana','sans-serif'">In brief, we want the View to have as little developer created code as possible and we certainly don’t want to be making decisions … to be writing conditional logic … in the View’s code-behind.<O:P></O:P></SPAN></P><P style="MARGIN: 0in 0in 10pt" ="Ms&#111;normal"><B style="mso-bidi-font-weight: normal"><SPAN style="FONT-SIZE: 9pt; LINE-HEIGHT: 115%; FONT-FAMILY: 'Verdana','sans-serif'">It follows that “every” View should have a corresponding ViewModel.<O:P></O:P></SPAN></B></P><P style="MARGIN: 0in 0in 10pt" ="Ms&#111;normal"><SPAN style="FONT-SIZE: 9pt; LINE-HEIGHT: 115%; FONT-FAMILY: 'Verdana','sans-serif'">This is why you have ModelExplorerView and ModelExplorerViewModel … and FormView and FormViewModel.<O:P></O:P></SPAN></P><P style="MARGIN: 0in 0in 10pt" ="Ms&#111;normal"><I style="mso-bidi-font-style: normal"><SPAN style="FONT-SIZE: 9pt; LINE-HEIGHT: 115%; FONT-FAMILY: 'Verdana','sans-serif'">Aside: there are always exceptions. I’m sure there is a truly dumb view that has no model to speak of and such simple controls that giving it the full MVVM treatment would be pedantry. I don’t have any examples of these so-called “autonomous views” in M.E. … but they are not hard to imagine. Confirmation dialogs might be an example.<O:P></O:P></SPAN></I></P><P style="MARGIN: 0in 0in 10pt" ="Ms&#111;normal"><B style="mso-bidi-font-weight: normal"><SPAN style="FONT-SIZE: 9pt; LINE-HEIGHT: 115%; FONT-FAMILY: 'Verdana','sans-serif'">FormViewModel drives two Views<O:P></O:P></SPAN></B></P><P style="MARGIN: 0in 0in 10pt" ="Ms&#111;normal"><SPAN style="FONT-SIZE: 9pt; LINE-HEIGHT: 115%; FONT-FAMILY: 'Verdana','sans-serif'">You may not have noticed that FormViewModel is the VM for both FormView and EmployeeFormView. There is no rule in my book that says that there must be one ViewModel for every View.<SPAN style="mso-spacerun: yes">&nbsp; </SPAN>Here it makes perfect sense. It would make perfect sense to have a WPF view and a Silverlight View share the same ViewModel. Views might differ depending upon the user; a View for someone who is vision impaired would be quite different from the “standard” view … and yet the two views could comfortably share the same ViewModel.<O:P></O:P></SPAN></P><P style="MARGIN: 0in 0in 10pt" ="Ms&#111;normal"><SPAN style="FONT-SIZE: 9pt; LINE-HEIGHT: 115%; FONT-FAMILY: 'Verdana','sans-serif'">The opposite case – a View that can be driven by more than one ViewModel – is a bit more unusual. But there are good examples. A chart view might be general purpose enough to be driven by very different ViewModels (one for order volume, another for customer service calls).<O:P></O:P></SPAN></P><P style="MARGIN: 0in 0in 10pt" ="Ms&#111;normal"><B style="mso-bidi-font-weight: normal"><SPAN style="FONT-SIZE: 9pt; LINE-HEIGHT: 115%; FONT-FAMILY: 'Verdana','sans-serif'">What you’d need for a new “Form”<O:P></O:P></SPAN></B></P><P style="MARGIN: 0in 0in 10pt" ="Ms&#111;normal"><SPAN style="FONT-SIZE: 9pt; LINE-HEIGHT: 115%; FONT-FAMILY: 'Verdana','sans-serif'">Suppose you are adding an “Order Entry Form”. You already have the Order and OrderDetails entities ready to go and have decided that it is ok to expose their properties in the view.<O:P></O:P></SPAN></P><P style="MARGIN: 0in 0in 10pt" ="Ms&#111;normal"><SPAN style="FONT-SIZE: 9pt; LINE-HEIGHT: 115%; FONT-FAMILY: 'Verdana','sans-serif'">You will extend the PersistenceService to retrieve the right entities; you might add an IOrderEntryPersistenceService interface to reduce the surface area of the module PersistenceService to just what you need for the order entry scenarios.<O:P></O:P></SPAN></P><P style="MARGIN: 0in 0in 10pt" ="Ms&#111;normal"><SPAN style="FONT-SIZE: 9pt; LINE-HEIGHT: 115%; FONT-FAMILY: 'Verdana','sans-serif'">You will need at least one View and corresponding ViewModel.<O:P></O:P></SPAN></P><P style="MARGIN: 0in 0in 10pt" ="Ms&#111;normal"><SPAN style="FONT-SIZE: 9pt; LINE-HEIGHT: 115%; FONT-FAMILY: 'Verdana','sans-serif'">We haven’t talked about how to compose big views (e.g., “forms”) from smaller constituent views; these would follow the MVVM pattern as well. But view composition is a topic for another day.<O:P></O:P></SPAN></P><P style="MARGIN: 0in 0in 10pt" ="Ms&#111;normal"><B style="mso-bidi-font-weight: normal"><SPAN style="FONT-SIZE: 9pt; LINE-HEIGHT: 115%; FONT-FAMILY: 'Verdana','sans-serif'">How do View and ViewModel interact?<O:P></O:P></SPAN></B></P><P style="MARGIN: 0in 0in 10pt" ="Ms&#111;normal"><SPAN style="FONT-SIZE: 9pt; LINE-HEIGHT: 115%; FONT-FAMILY: 'Verdana','sans-serif'">That really is too big … and controversial … a topic for this post. In brief:<O:P></O:P></SPAN></P><P style="MARGIN: 0in 0in 0pt 0.5in; TEXT-INDENT: -0.25in; mso-list: l0 level1 lfo1" ="MsoListParagraphCxSpFirst"><SPAN style="FONT-SIZE: 9pt; LINE-HEIGHT: 115%; FONT-FAMILY: Symbol; mso-fareast-font-family: Symbol; mso-bidi-font-family: Symbol"><SPAN style="mso-list: Ignore">·<SPAN style="FONT: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN></SPAN></SPAN><SPAN style="FONT-SIZE: 9pt; LINE-HEIGHT: 115%; FONT-FAMILY: 'Verdana','sans-serif'">A View “knows” its ViewModel and “talks” to the ViewModel by binding to VM properties and by calling upon ViewModel methods in its code-behind (see below).</P><DIV>&nbsp;</DIV><DIV><O:P></O:P></DIV></SPAN><P style="MARGIN: 0in 0in 10pt 0.5in; TEXT-INDENT: -0.25in; mso-list: l0 level1 lfo1" ="MsoListParagraphCxSpLast"><SPAN style="FONT-SIZE: 9pt; LINE-HEIGHT: 115%; FONT-FAMILY: Symbol; mso-fareast-font-family: Symbol; mso-bidi-font-family: Symbol"><SPAN style="mso-list: Ignore">·<SPAN style="FONT: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN></SPAN></SPAN><SPAN style="FONT-SIZE: 9pt; LINE-HEIGHT: 115%; FONT-FAMILY: 'Verdana','sans-serif'">In this version of the M.E., the ViewModel does NOT know its View. The ViewModel needs some way to call upon the View when it is initiating the communication (e.g., when it wants the view to display a message). Binding won't work everywhere. <SPAN style="mso-spacerun: yes">&nbsp;</SPAN>In this approach, the View gives the ViewModel a delegate so the ViewModel can call upon the delegate.<O:P></O:P></SPAN></P><P style="MARGIN: 0in 0in 10pt" ="Ms&#111;normal"><SPAN style="FONT-SIZE: 9pt; LINE-HEIGHT: 115%; FONT-FAMILY: 'Verdana','sans-serif'">ModelExplorerView.xaml.cs illustrates the second bullet in this line:<O:P></O:P></SPAN></P><P style="MARGIN: 0in 0in 10pt 0.5in" ="Ms&#111;normal"><SPAN style="FONT-SIZE: 9pt; LINE-HEIGHT: 115%; FONT-FAMILY: 'Courier New'">ViewModel.MessageDisplayer = <BR><SPAN style="mso-spacerun: yes">&nbsp; </SPAN>new TextBlockMessageDisplayer(_message);<O:P></O:P></SPAN></P><P style="MARGIN: 0in 0in 10pt" ="Ms&#111;normal"><SPAN style="FONT-SIZE: 9pt; LINE-HEIGHT: 115%; FONT-FAMILY: 'Verdana','sans-serif'">The View gives the ViewModel an instance of a helper object that implements </SPAN><SPAN style="FONT-SIZE: 9pt; LINE-HEIGHT: 115%; FONT-FAMILY: 'Verdana','sans-serif'; mso-bidi-font-family: 'Courier New'">IMessageDisplayer</SPAN><SPAN style="FONT-SIZE: 9pt; LINE-HEIGHT: 115%; FONT-FAMILY: 'Verdana','sans-serif'">. That interface has a </SPAN><SPAN style="FONT-SIZE: 9pt; LINE-HEIGHT: 115%; FONT-FAMILY: 'Verdana','sans-serif'; mso-bidi-font-family: 'Courier New'">Display</SPAN><SPAN style="FONT-SIZE: 9pt; LINE-HEIGHT: 115%; FONT-FAMILY: 'Verdana','sans-serif'">(message, messageType) method; the ViewModel can call it anytime it has something to tell the View.<O:P></O:P></SPAN></P><P style="MARGIN: 0in 0in 10pt" ="Ms&#111;normal"><SPAN style="FONT-SIZE: 9pt; LINE-HEIGHT: 115%; FONT-FAMILY: 'Verdana','sans-serif'">Why couldn’t we just bind the View to a property of the ViewModel? Because the ViewModel must give the view two pieces of information at the same time – the message and the type of the message. There is no easy binding to do this job.<O:P></O:P></SPAN></P><P style="MARGIN: 0in 0in 10pt" ="Ms&#111;normal"><I style="mso-bidi-font-style: normal"><SPAN style="FONT-SIZE: 9pt; LINE-HEIGHT: 115%; FONT-FAMILY: 'Verdana','sans-serif'">Aside: There are people who really hate this approach. They strongly prefer that there be an IModelExplorerView interface with a Display method. The View passes itself to the ViewModel <SPAN style="mso-spacerun: yes">&nbsp;</SPAN>… <SPAN style="mso-spacerun: yes">&nbsp;</SPAN>as an instance of IModelExplorerView; the ViewModel<SPAN style="mso-spacerun: yes">&nbsp; </SPAN>can then call back on the view through that interface. We will not discuss here the merits and challenges of this approach.<O:P></O:P></SPAN></I></P><P style="MARGIN: 0in 0in 10pt" ="Ms&#111;normal"><B style="mso-bidi-font-weight: normal"><SPAN style="FONT-SIZE: 9pt; LINE-HEIGHT: 115%; FONT-FAMILY: 'Verdana','sans-serif'">FormViewController<O:P></O:P></SPAN></B></P><P style="MARGIN: 0in 0in 10pt" ="Ms&#111;normal"><SPAN style="FONT-SIZE: 9pt; LINE-HEIGHT: 115%; FONT-FAMILY: 'Verdana','sans-serif'">No, this controller is not a participant in the M-V-VM pattern. It is a helper class with an unfortunate name that invites comparison with the central actor in another UI separation pattern: MVC.<O:P></O:P></SPAN></P><P style="MARGIN: 0in 0in 10pt" ="Ms&#111;normal"><SPAN style="FONT-SIZE: 9pt; LINE-HEIGHT: 115%; FONT-FAMILY: 'Verdana','sans-serif'">Perhaps I should have called it “FormViewMicroController” for it is an example of what Jeremy Miller calls a “<a href="http://codebetter.com/blogs/jeremy.miller/archive/2007/10/21/build-your-own-cab-15-microc&#111;ntrollers.aspxhttp:/codebetter.com/blogs/jeremy.miller/archive/2007/10/21/build-your-own-cab-15-microc&#111;ntrollers.aspx" target="_blank"><U>MicroController</U></A>”: <SPAN style="mso-spacerun: yes">&nbsp;</SPAN>a small, re-usable controller class “to govern some atomic part of the screen.” <O:P></O:P></SPAN></P><P style="MARGIN: 0in 0in 10pt" ="Ms&#111;normal"><SPAN style="FONT-SIZE: 9pt; LINE-HEIGHT: 115%; FONT-FAMILY: 'Verdana','sans-serif'">The ideas is that there is a chunk of purely-UI logic that gets used in multiple views. The logic doesn’t belong in the ViewModel because it is highly aware of specific UI controls.<O:P></O:P></SPAN></P><P style="MARGIN: 0in 0in 10pt" ="Ms&#111;normal"><SPAN style="FONT-SIZE: 9pt; LINE-HEIGHT: 115%; FONT-FAMILY: 'Verdana','sans-serif'">As a rule, ViewModels should speak entirely in terms of non-UI types: strings, integers, enumerations, helper classes. They shouldn’t have a dependency on Silverlight controls, for example. If we stuck to that rule, we could re-use a ViewModel to drive a WPF client or maybe even a WinForms or ASP client (but don’t count on it). More importantly, by keeping UI dependencies out of the ViewModel, we make the ViewModel easier to test in a non-UI test harness.<O:P></O:P></SPAN></P><P style="MARGIN: 0in 0in 10pt" ="Ms&#111;normal"><SPAN style="FONT-SIZE: 9pt; LINE-HEIGHT: 115%; FONT-FAMILY: 'Verdana','sans-serif'">The kind of logic we’re encapsulating in a MicroController is very UI-aware. The FormViewController in M.E. knows about the FormView and the EmployeeFormView for example.<O:P></O:P></SPAN></P><P style="MARGIN: 0in 0in 10pt" ="Ms&#111;normal"><I style="mso-bidi-font-style: normal"><SPAN style="FONT-SIZE: 9pt; LINE-HEIGHT: 115%; FONT-FAMILY: 'Verdana','sans-serif'">Aside: I must admit that the FormViewController is a hack. I do NOT think that this is the best way to dispatch an Edit button click to the appropriate MVVM triad. But, without Dependency Injection, I couldn’t think of a clean and simple way to do what it does. I certainly wasn’t going to embed the FormViewController’s conditional logic directly into the view’s code-behind!<SPAN style="mso-spacerun: yes">&nbsp; </SPAN>So I rolled this thing. Try <U>not</U> to follow my example.<O:P></O:P></SPAN></I></P><P style="MARGIN: 0in 0in 10pt" ="Ms&#111;normal"><B style="mso-bidi-font-weight: normal"><SPAN style="FONT-SIZE: 9pt; LINE-HEIGHT: 115%; FONT-FAMILY: 'Verdana','sans-serif'">SimpleCommandController – a better MicroController example<O:P></O:P></SPAN></B></P><P style="MARGIN: 0in 0in 10pt" ="Ms&#111;normal"><SPAN style="FONT-SIZE: 9pt; LINE-HEIGHT: 115%; FONT-FAMILY: 'Verdana','sans-serif'">I am a little more comfortable with this MicroController which binds View buttons to ViewModel methods. In my latest version, it looks like this:<O:P></O:P></SPAN></P><P style="MARGIN: 0in 0in 0pt" ="Ms&#111;normal"><SPAN style="FONT-SIZE: 9pt; LINE-HEIGHT: 115%; FONT-FAMILY: 'Courier New'"><SPAN style="mso-spacerun: yes">&nbsp;</SPAN><SPAN style="mso-spacerun: yes">&nbsp; </SPAN>CommandController = new SimpleCommandController()<O:P></O:P></SPAN></P><P style="MARGIN: 0in 0in 0pt" ="Ms&#111;normal"><SPAN style="FONT-SIZE: 9pt; LINE-HEIGHT: 115%; FONT-FAMILY: 'Courier New'"><SPAN style="mso-spacerun: yes">&nbsp;</SPAN><SPAN style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp; </SPAN>.Add(_queryButton, ViewModel.Fetch)<O:P></O:P></SPAN></P><P style="MARGIN: 0in 0in 0pt" ="Ms&#111;normal"><SPAN style="FONT-SIZE: 9pt; LINE-HEIGHT: 115%; FONT-FAMILY: 'Courier New'"><SPAN style="mso-spacerun: yes">&nbsp;</SPAN><SPAN style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp; </SPAN>.Add(_queryCombo, ViewModel.Fetch)<O:P></O:P></SPAN></P><P style="MARGIN: 0in 0in 0pt" ="Ms&#111;normal"><SPAN style="FONT-SIZE: 9pt; LINE-HEIGHT: 115%; FONT-FAMILY: 'Courier New'"><SPAN style="mso-spacerun: yes">&nbsp;</SPAN><SPAN style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp; </SPAN>.Add(_addButton, ViewModel.Add)<O:P></O:P></SPAN></P><P style="MARGIN: 0in 0in 0pt" ="Ms&#111;normal"><SPAN style="FONT-SIZE: 9pt; LINE-HEIGHT: 115%; FONT-FAMILY: 'Courier New'"><SPAN style="mso-spacerun: yes">&nbsp;</SPAN><SPAN style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp; </SPAN>.Add(_editButton, () =&gt; FormViewController.Show(_dataGrid))<O:P></O:P></SPAN></P><P style="MARGIN: 0in 0in 0pt" ="Ms&#111;normal"><SPAN style="FONT-SIZE: 9pt; LINE-HEIGHT: 115%; FONT-FAMILY: 'Courier New'"><SPAN style="mso-spacerun: yes">&nbsp;</SPAN><SPAN style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp; </SPAN>.Add(_deleteButton, ViewModel.Delete)<O:P></O:P></SPAN></P><P style="MARGIN: 0in 0in 0pt" ="Ms&#111;normal"><SPAN style="FONT-SIZE: 9pt; LINE-HEIGHT: 115%; FONT-FAMILY: 'Courier New'"><SPAN style="mso-spacerun: yes">&nbsp;</SPAN><SPAN style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp; </SPAN>.Add(_saveButton, ViewModel.Save)<O:P></O:P></SPAN></P><P style="MARGIN: 0in 0in 0pt" ="Ms&#111;normal"><SPAN style="FONT-SIZE: 9pt; LINE-HEIGHT: 115%; FONT-FAMILY: 'Courier New'"><SPAN style="mso-spacerun: yes">&nbsp;</SPAN><SPAN style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp; </SPAN>.Add(_clearButton, ViewModel.Clear)<O:P></O:P></SPAN></P><P style="MARGIN: 0in 0in 0pt" ="Ms&#111;normal"><SPAN style="FONT-SIZE: 9pt; LINE-HEIGHT: 115%; FONT-FAMILY: 'Courier New'"><SPAN style="mso-spacerun: yes">&nbsp;</SPAN><SPAN style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp; </SPAN>.Add(_toFileButton, ViewModel.CacheToFile)<O:P></O:P></SPAN></P><P style="MARGIN: 0in 0in 0pt" ="Ms&#111;normal"><SPAN style="FONT-SIZE: 9pt; LINE-HEIGHT: 115%; FONT-FAMILY: 'Courier New'"><SPAN style="mso-spacerun: yes">&nbsp;</SPAN><SPAN style="mso-spacerun: yes">&nbsp;</SPAN><SPAN style="mso-spacerun: yes">&nbsp;&nbsp; </SPAN>.Add(_fromFileButton, ViewModel.FileToCache)<O:P></O:P></SPAN></P><P style="MARGIN: 0in 0in 0pt" ="Ms&#111;normal"><SPAN style="FONT-SIZE: 9pt; LINE-HEIGHT: 115%; FONT-FAMILY: 'Courier New'"><SPAN style="mso-spacerun: yes">&nbsp;</SPAN><SPAN style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp; </SPAN>.Add(_connectDisconnectButton, ViewModel.ToggleConnectedness);<O:P></O:P></SPAN></P><P style="MARGIN: 0in 0in 0pt" ="Ms&#111;normal"><SPAN style="FONT-SIZE: 9pt; LINE-HEIGHT: 115%; FONT-FAMILY: 'Courier New'"><O:P>&nbsp;</O:P></SPAN></P><P style="MARGIN: 0in 0in 10pt" ="Ms&#111;normal"><SPAN style="FONT-SIZE: 9pt; LINE-HEIGHT: 115%; FONT-FAMILY: 'Verdana','sans-serif'">It is quite general purpose; you can imagine using it on other views that sport buttons.<O:P></O:P></SPAN></P><P style="MARGIN: 0in 0in 10pt" ="Ms&#111;normal"><SPAN style="FONT-SIZE: 9pt; LINE-HEIGHT: 115%; FONT-FAMILY: 'Verdana','sans-serif'">This one instance manages to take the place of ten event handlers, thus eliminating a ton of code that looks pretty much the same.<O:P></O:P></SPAN></P><P style="MARGIN: 0in 0in 10pt" ="Ms&#111;normal"><I style="mso-bidi-font-style: normal"><SPAN style="FONT-SIZE: 9pt; LINE-HEIGHT: 115%; FONT-FAMILY: 'Verdana','sans-serif'">Aside: you might prefer to bind the buttons to the ViewModel in xaml. Better still, you’d like to bind to implementations of ICommand. To do this right, you need a commanding infrastructure such as you’ll find in Prism. That would have been overkill for M.E.<O:P></O:P></SPAN></I></P><P style="MARGIN: 0in 0in 10pt" ="Ms&#111;normal"><SPAN style="FONT-SIZE: 9pt; LINE-HEIGHT: 115%; FONT-FAMILY: 'Verdana','sans-serif'">My point is that FormViewController and SimpleCommandController are helpers. They help us factor out commonalities from view to view.<SPAN style="mso-spacerun: yes">&nbsp; </SPAN>Or (as in FormViewController) we use them to eliminate conditional logic from a view’s code-behind. Because these helpers are small and focused on a single job, they can be tested easily without the baggage of any particular view class.<O:P></O:P></SPAN></P><P style="MARGIN: 0in 0in 10pt" ="Ms&#111;normal"><B style="mso-bidi-font-weight: normal"><SPAN style="FONT-SIZE: 9pt; LINE-HEIGHT: 115%; FONT-FAMILY: 'Verdana','sans-serif'">For More Information<O:P></O:P></SPAN></B></P><P style="MARGIN: 0in 0in 10pt" ="Ms&#111;normal"><SPAN style="FONT-SIZE: 9pt; LINE-HEIGHT: 115%; FONT-FAMILY: 'Verdana','sans-serif'">There’s a ton of references to give. But I think it would be better to get this posted and follow up later. Until then, don’t be bashful about searching the web on your own.</SPAN></P><P style="MARGIN: 0in 0in 10pt" ="Ms&#111;normal"><FONT face=Calibri size=3>Ward</FONT></P><span style="font-size:10px"><br /><br />Edited by WardBell - 23-Apr-2009 at 2:29am</span>]]>
   </description>
   <pubDate>Thu, 23 Apr 2009 02:24:18 -700</pubDate>
   <guid isPermaLink="true">http://www.ideablade.com/forum/forum_posts.asp?TID=1229&amp;PID=4441#4441</guid>
  </item> 
  <item>
   <title>Digging Deeper! : I agree with Ben, I was eluding...</title>
   <link>http://www.ideablade.com/forum/forum_posts.asp?TID=1229&amp;PID=4436#4436</link>
   <description>
    <![CDATA[<strong>Author:</strong> <a href="http://www.ideablade.com/forum/member_profile.asp?PF=470" rel="nofollow">bigfish</a><br /><strong>Subject:</strong> 1229<br /><strong>Posted:</strong> 22-Apr-2009 at 2:25pm<br /><br />I agree with Ben, I was eluding to this on point 4 of this post.&nbsp; <a href="http://www.ideablade.com/forum/forum_posts.asp?TID=1218" target="_blank">http://www.ideablade.com/forum/forum_posts.asp?TID=1218</A><DIV></DIV>Can't wait for your response Ward. Thanks.]]>
   </description>
   <pubDate>Wed, 22 Apr 2009 14:25:45 -700</pubDate>
   <guid isPermaLink="true">http://www.ideablade.com/forum/forum_posts.asp?TID=1229&amp;PID=4436#4436</guid>
  </item> 
  <item>
   <title>Digging Deeper! : Great questions. Give me another...</title>
   <link>http://www.ideablade.com/forum/forum_posts.asp?TID=1229&amp;PID=4433#4433</link>
   <description>
    <![CDATA[<strong>Author:</strong> <a href="http://www.ideablade.com/forum/member_profile.asp?PF=482" rel="nofollow">WardBell</a><br /><strong>Subject:</strong> 1229<br /><strong>Posted:</strong> 22-Apr-2009 at 11:40am<br /><br /><P>Great questions. Give me another day to compose a reply. And hold me to it! :-)&nbsp;&nbsp; Ward</P>]]>
   </description>
   <pubDate>Wed, 22 Apr 2009 11:40:49 -700</pubDate>
   <guid isPermaLink="true">http://www.ideablade.com/forum/forum_posts.asp?TID=1229&amp;PID=4433#4433</guid>
  </item> 
  <item>
   <title>Digging Deeper! :  Hi Ward;As I&amp;#039;m looking...</title>
   <link>http://www.ideablade.com/forum/forum_posts.asp?TID=1229&amp;PID=4428#4428</link>
   <description>
    <![CDATA[<strong>Author:</strong> <a href="http://www.ideablade.com/forum/member_profile.asp?PF=425" rel="nofollow">BenHayat</a><br /><strong>Subject:</strong> 1229<br /><strong>Posted:</strong> 21-Apr-2009 at 6:24am<br /><br />Hi Ward;<br><br>As I'm looking at the code that the template produces, I thought i ask a few questions and anyone else interested in the MVVM implementation. As you mentioned, there many different text and theories on this subject and I'm sure yours is as good as the rest. But since you're providing that pattern here, I thought I ask you these:<br><br>The ModelExplorer page, you have:<br>&nbsp; 1 - ModelExplorer_ViewModel.cs<br>&nbsp; 2 - ModelExplorer_View.xaml/cs<br>&nbsp; 3 - ModelExplorer_PersistenceService.cs<br><br>The data form entry, you have:<br>&nbsp; 1 - Form_ViewModel.cs<br>&nbsp; 2 - Form_View.xaml/cs<br>&nbsp; 3 - Form_ViewController.cs<br>&nbsp; <br>And then you have one:<br>&nbsp; Model.Designer.cs<br><br>And you also have the "Persistence" Folder with more classes.<br><br>a) What I'm trying to find a pattern and a description of what goes where to start with?<br>b) Should every form in the Silverlight project have (ViewModel.cs, View.xaml/cs, ViewController.cs)?<br>c) Is the PersistenceService.cs a class that belongs to one form or is it more like shared among all forms?<br>d) Suppose, I need to create a new Order entry form, based on your formula, what does a developer need, every time he needs to add more forms to the project.<br>e) I also wanted to ask, if it would be possible to give a layout of classes that need to be created and how each interacted with each other. If that's too much to ask, do you have any links that describes your direction in more along with a pattern and guidelines. <br><br>Perhaps you would like to answer these here or create a blog that gives a more detail and education on how MVVM and DevForce should be designed together.<br><br>Much appreciated!<br><span style="font-size:10px"><br /><br />Edited by BenHayat - 21-Apr-2009 at 6:41am</span>]]>
   </description>
   <pubDate>Tue, 21 Apr 2009 06:24:40 -700</pubDate>
   <guid isPermaLink="true">http://www.ideablade.com/forum/forum_posts.asp?TID=1229&amp;PID=4428#4428</guid>
  </item> 
 </channel>
</rss>