none
A vent about MVVM Development

    Question

  • After doing a lot of research this weekend, I wanted to voice my opinion on our mandated 'architecture'.  I am not a fan nor will I be a fan of WPF/Silverlight development in which one has to adhere to a complete "Data Binding" model and totally separating the user interface from the design --especially when the business rules dictate a complex interaction between user interface components and the data which is being modified.

    To think that MVVM can purely exist is a panacea.  If you are designing a 'record editor' where you can do simple CRUD operations, it's icing on the cake and very powerful.  When the User Interface has to conform to certain rules based on the business logic contained in the ViewModel, you then have to start wondering how you're going to update the User Interface with pure data binding.  I recall having to write extra code just to convert a 'true' or 'false' bool value into a "Visibility.Collapsed" or "Visibility.Visible" value.  In some cases not just writing a lot of converters or validators, but adding additional properties to your 'ViewModel' in order to simplify the property bindings.

    Now, consider a case where all you are allowed to do is just create your main User Interface in XAML, your architect tells you that you have to use MVVM and you need to do some complex User Interface manipulation, such as dragging and dropping, enabling or disabling items based on business rules during User Interface changes --but with *no* code-behind.  (The ViewModel can get pretty darn big just to create complex rules for enabling or disabling items.)

    MVVM is an *awesome* template for record editing applications and simple projects, but I would *never* recommend it for a large-scale application.  Just look at the controversy others have (most of which I agree with) regarding this pattern (http://en.wikipedia.org/wiki/MVVM):

    -----------------------

    "There are currently three main areas of criticism regarding the MVVM pattern. The first is that MVVM currently lacks standardization from Microsoft both in implementation and in toolsets. For example, the community has some lack of clarity about where and whether to implement View logic in the View layer or the ViewModel. Given that the MVVM pattern is still relatively new, and that new tool-sets, walkthroughs, or patterns, such as Onyx, Prism, the Microsoft WPF Toolkit, Crack.net, Caliburn and MVVM Light Toolkit are being released, this problem may be solved over time. Microsoft has announced in discussion boards that the MVVM template pattern will be released in Visual Studio 2010.

    The second comes from MVVM creator John Gossman himself, who points out that the overhead in implementing MVVM is “overkill” for simple UI operations. He also states that for larger applications, generalizing the View layer becomes more difficult. Moreover, he illustrates that data binding, if not managed well, can result in a considerable excess of metadata in an application. Given these limitations, MVVM may have a practical minimum and maximum size for the type of application it can support, suggesting it may not perform well with large enterprise applications.

    The third is that the exercise in creating large numbers of data bindings to the ViewModel results in duplicate code and maintenance problems. Additionally, because of the nature of the semantics of data bindings, critics suggest that the ViewModel does not directly describe the View."

    -----------------------

    What really irritates me is that I am forced to waste so much time on how to try and figure out how a complex User Interface will work together with a suitable "ViewModel" all for the sake of being more "testable".  I could cobble together a pretty darn good application and still be able to split up the work among User Interface and code-behind developers.  I think adopting a non-industry standard, seemingly "best practices" ideology just because it seems 'cool' and it's "there" is the wrong approach to application development.

    The MVVM creator himself admits to such pitfalls in his own design; I wonder why we still have to adhere to such a strict, difficult and at times very time-consuming design because it is considered "best practices" when proof of such does not yet exist.  If it hasn't been conveyed that this is the most annoying, difficult, round-about, unnatural, twisted, bizzare, convoluted, confusing, amazing way to develop software, then let my voice be heard.  If the proponents of this model wish to start User Interface development (instead of pushing such tasks to other developers who work with the UI) and show me, nay *tell* me how it is not one of the most difficult if not impossible paradigms to code against, let them stand forth and waste their time, not mine or yours.

    Now, I could have used "not best practices", but could have followed coding styles and standards as well as design guidelines and got an application "out the door" even if it irritated our architect's sensibilities without having to do some of the intricate research involved in bending XAML for the purpose of making event handling declarative for things other than "button clicks" which apparently the designers of this practice assume to be the only operation a human would ever consider using in an application.

    What about dragging, dropping, docking a window, undocking a window -- to assume the audience does nothing more than point and click a 'button' (yes, the architecture supports only a button click when it comes to commands, but no other events).  The paradigm is perfect for people who create applications that are mere "editing" tools to manage form-based records.

    I apologize for the vent; however, I like to take the 'pragmatic' approach to things and now when others tout "best practices", I am seven days a skeptic.

    If event driven programming were so taboo for WPF and Silverlight developers, then Microsoft would have prohibited its use out of the gates.

    • Moved by mbanavige Wednesday, September 14, 2011 11:35 PM Migration data
    Sunday, January 31, 2010 1:17 PM

Answers

  • Jason, you've raised some good points, let me address them in a question/answer format for convenience sake:

    Q: When to use the code-behind?
    A: My golden rule is this, don't let view-specific details leak into your ViewModel, unless of course the View details are the Model itself. Now, to follow this I first try to use existing infrastructure/tooling like binding, behaviors etc, if that is not possible then I try to create custom behaviors/triggers/actions per the need, and if that is not also appropriate then I use code-behind. That is a simple enuff workflow?

    Q. You have an Orange object and you want to visualize it as some sort of Document Windows?
    I need more specifics, but it seems to me it is appropriate to hold the Orange into a "Document" object, and then the open/closed, docked/undocked state etc will be encapsulated in the Document object rather than leaking your business model (the Orange object). To use the document, you will expose it as an observable collection, which you can bind to the Tabs collection. Have a look at Calibrum it has pretty good guidance around such issues. Couldn't resist this, don't try to make apple juice out of oranges :)

    Q. About adopting nRoute?
    First, nRoute for now is SL only - and in case you are not be able to adopt it as a whole, you have the source code so pick and choose the stuff you need. I say, no need to reinvent the wheel. Also nRoute is not limited to UI related stuff, it has a lot of infrastructure related features - likes services, modules, event-aggregators, view-models, MEF like framework etc. And it has a lot of unique features that really realize MVVM, do look at some of the sample projects on Codeplex as plenty of are non-trivial.  

    Q. About "lots" of up-from work?
    What I meant by that was you have to on the onset divide your application's functionality between Views, ViewModels, Services, or ViewServices etc. And that is what gets people I suppose, but once you are used to it, it is not really that big of a deal. I perhaps have a perfect example for you, I took this Sudoku game (by Lee Saunders) which was essentially implemented in the code-behind, and in a step-by-step fashion I carved a MVVM application out of it. And you have both the pre and post MVVM code-sets available to look at, along with an accompanying blog post that show how to transform it to MVVM:

    Pre-MVVM Sudoku Info: http://oldschooldotnet.blogspot.com/2009/03/sudoku-in-silverlight.html
    Post-MVVM Sudoku Info (using nRoute): http://www.orktane.com/Blog/post/2010/01/23/iPhone-Sudoku-in-Silverlight-using-MVVM.aspx

    Note, both the implementations rely on the same engine to generate the Sudoku puzzle. And, after you have gone through it, consider in which code-set will it be easier to implement a new feature (like pencil marking) that has been requested of me. Also, mark on the clarity and testability of the code if you can.

    Q. About using a toolset for a design pattern?
    Design patterns are implementation-agnostic, that doesn't mean for a specific implementation you can't use a toolset - hell, .NET framework is a genormas toolset. And also I often find people think whatever Microsoft delivers is the only starting point for your application, well breaking new, it's not always appropriate - especially for less matured technologies like WPF/SL.

    Q. About things being less than ideal?
    Yes that is true, less than ideal solutions do turn up, but it has more to do with the limitations of SL than the MVVM pattern - and till now I've only had 3 or 4 such situations which is far from tainting the whole situation as flawed.

    Q. About getting your head-around?
    I think for a lot of people (including me) there is a light-bulb moment for MVVM, when you reach that the your head-and-tail will be all around it, don't worry :) For a recent case in point see http://blogs.silverlight.net/blogs/jesseliberty/archive/2010/01/28/mvvm-it-s-not-kool-aid.aspx

    Q. About the books?
    I've heard on twitter couple of people thinking about writing MVVM books - Shawn Wildermuth was the most recent of those, tell him if you want one. But for myself, I like to live on the blogging-edge, it's more upto date and interactive than any book can be.

    Oky, this is getting long let me leave it here - and don't worry about directing it onto me, it's a good learning exercise.

    Rishi

    Monday, February 01, 2010 11:59 AM
  • It's a good two cents, and I appreciate it. However, I think a lot of people confuse "different" with "difficult." Once you master MVVM, it's not difficult at all and you don't have to shoot through hoops. Like transitioning from procedural code to object-oriented code, transitioning from older models (heck, most people didn't have a robust architecture and just slammed data readers into combo boxes because that's what the examples did) like control-controller, etc, to MVVM requires changing your way of thinking and really understanding the databinding model and hierarchy.

    Your view model doesn't have to know a thing about your view.

    For example, let's assume you have a list of Widgets and want the currently selected Widget. Many people feel they have to somehow tap into a selected item changed event or something similar, which means the MVVM knows about the UI element or there is code-behind.

    In reality, it's as simple as having a Widgets list and a current Widget on your view model:

    public ObservableCollection<Widget> Widgets { get; set; }

    public Widget CurrentWidget { get; set; }

    Then binding the list box appropriately:

    <ListBox ItemsSource="{Binding Widgets}" SelectedItem={Binding CurrentWidget, Mode=TwoWay}"/>

    Then you are fine and the view model doesn't care.

    You can also nest view models and have other patterns.

    I've been writing some fairly large and complex Silverlight applications with very heavy logic, and have yet to find a place where MVVM didn't fit well. I also don't go through hoops and try to create exotic patterns just to accommodate UI behaviors ... if there is an animation I need to fire or something UI specific, rather than spending a day extending my ViewModel for some abstracted behavior that will fire the UI event, I simply put a code behind event where a code-behind event makes sense.

    I don't think code-behind is appropriate for moving data at all. However, it is absolutely approrpiately in my eyes to use code behind for a user control to manage the visual state and elements of that control ... that is keeping the UI logic in the UI layer, and is far better in my opinion than dragging it down to the view model.

    That's my 1 1/2 cents.

    Tuesday, February 02, 2010 2:51 PM

All replies

  • I couldn't agree more. But then, you already knew that :)

    Sometimes I get frustrated watching people (on here and elsewhere) obviously spending hours and hours trying to work out a way to do what they want to do using the pattern/practice of the moment, when they could have just written some code in 10 minutes. I'm not saying MVVM or any of these things is bad or that they're not really great in many situations, just that sometimes people can lose perspective.

    Sunday, January 31, 2010 2:01 PM
  • Absolutely Tim,

    The architect says "little if no code-behind", but a complex User Interface such as dockable windows really doesn't need to have its complexity pushed into a ViewModel.  In a lot of tests, prototypes and in a project I've worked with, the ViewModel code, which is *supposed* to be seperated from the User Interface is just that, but it had to be made more complex in order to support the User Interface requirements.

    An example?  Ok, Let's say I have three input boxes on a form along with one check box.  If the check-box is checked, then two of the textboxes are disabled, but not if someone entered text into the first.  I can't do this with traditional even handling, instead, I have to add a new assembly to my references to get commanding and add more mark-up to my XAML.  In some cases, I can't even use 'commanding', because I need to watch for other events.  Gee, it would be nice if life were distilled to more than a simple "button click", but apparently the original designers had no vision beyond that.  (The Expression Blend team, however, had better thoughts.)

    A lot of times, it seems as if the UI logic is being pushed into the ViewModel, making it more complicated than it really needs to be.  DataBinding lends itself well the editing a record.  How many attributes do I need to add to my XAML declaratively in order to ensure that all business logic is going to be done correctly?  Show me one real world example (and I don't think Visual Studio 2010 is applicable since it is still in Beta and you can't see the code) where an enterprise application has been built and solidly run using MVVM in 'true' production in the 'real' world and where it has been tried and true to the point it is acceptable by all who use it.

    " just that sometimes people can lose perspective." ... no truer words have ever been spoken.  I just wish I can change the perspective of the employers who tell me I have to do things *this way* because the arthictect's word is gold.

    I apologize for the rant, once again.

    Sunday, January 31, 2010 3:08 PM
  • You raise all good points. MVVM is a fantastic pattern where it is a fantastic pattern. It's not when you try to fit a square peg into a round hole. There are certain behaviors, such as auto-selecting an item when a combobox is bound, for example, that just make sense to do in the UI using the events provided. They may be abstracted as behaviors but there is no reason whatsoever my view model needs to understand the combo box loaded event.

    Another example is what you mentioned about collapsed. That is a case where sometimes binding to other elements on the page makes more sense than the view model, and certainly visual state manager. Instead of firing a converter, why not have the view model raise an event that moves the control to a new view state? Then the transition and heavy UI elements can be managered where they belong (in the XAML) rather than in the view model.

    I guess the final piece is that I do believe code should be testable. However, that does not mandate MVVM. I have many behaviors that I test regularly in my code using the Silverlight Unit Testing Framework that test the UI interaction directly, by binding a control to a test surface and then inspecting properties. This is perfectly valid. In a quality design, you will still be coding to interfaces, not concrete services, etc, so testing complex UI behavior should be about abstracting the UI controller or controller from the backend and isolating the behaviors to test, not forcing those behaviors into an unnatural pattern.

    Best of success with your project and with hopefully being able to demonstrate some value in looking at other patterns that may be more relevant to your particular situation. It is dangerous for anyone in an architectural role to consider a specific pattern or framework dogma.

    Sunday, January 31, 2010 4:32 PM
  • Hi Jason, I can understand your and other peoples' frustration about MVVM and the guidance surrounding it. I understand there is a lot of community noise and push towards to MVVM, but little in the form of tooling - in fact pure/out-of-the-box MVVM development might be even harder than one may suspect (especially beyond the CRUD level as you rightly said). And I know so, because I went through the same pain points, and consequently developed my own tooling called the nRoute framework (see http://nroute.codeplex.com/).

    I'll address your technical points, but first understand that in addition to the View-ViewModel separation and the Binding infrastructure, you need to add behaviors, triggers and actions into the mix. They provide View-specific re-usable executable-blocks that help keep View details in the View - and keeping the View things in the View is half the monkey dance that is known as MVVM. This is not a new concept by any means, it is the same old separation of concern thing but with the View-ViewModel twist.

    To address your technical questions/concerns I'll specifically reference stuff currently available in nRoute (samples are on my blog):

    • About the Visibility thing, very simple, we have a bindable behavior for toggling the visibility called BoolValueVisibilityBehavior (also see NullValueVisibilityBehavior), this will take less than 10 secs to hook up
    • About the problem of writing converters, in nRoute we have the concept of ValueConverter Relay using which you can write the Converter as a strongly-typed lambda statement either in your code-behind or in your ViewModel. Setting up a ValueConverterRelay takes 2 lines of code, one in xaml as a static resource and another in your code-behind
    • About showing hiding stuff and other types of conditional logic in your View - for that in nRoute we have something called ValueTriggers which can on a specific condition occurring take one or more actions in your View. And the actions can be hiding or showing stuff etc, but importantly the triggers can be triggered via something happening in your View or ViewModel, either-case
    • Your query about handling UI things other than through simple event handling, can be taken care by pairing a trigger with one or more actions - triggers can be quite complex, and they are not constrained to events-based things only, so for example you could do video-recognition or time based triggers etc. And using any sort of triggers, you can execute one or more commands in your ViewModel - see the ExecuteCommandAction action-behavior in nRoute. Now
    • Dragging, dropping and docking etc can also be setup as behaviors, and the data-exchanged taken care via either triggers or two-way binding - but remember one thing, you should not confuse control-type actions with those that should trigger changes in your ViewModel which happens to be a common mistake. Further, something called ReverseCommands (which are basically commands that trigger one or more actions in your View) also help co-ordinate more complex operations
    • About the checkbox state, simple to do with ValueTriggers - so like when your checkbox's check state changes you can set up a ValueTrigger to set a Textbox to be disabled or enabled. Alternatively, if you want a very peculiar logic, just write a behavior for it which shouldn't take more than a couple of extra lines of code and as a bonus it will be nicely encapsulated

    I'll add that in addition to behaviors stuff, for some advanced scenarios consider the use of message-broker/event-aggregator that allow loosely-coupled communications to and from ViewModels, in nRoute we have an IObservable based messaging-broker. Further, we have things ViewServices that I suspect you might really need to keep the ViewModel separation thing going. Similarly, there are lots of other tid-bits helpful for MVVM style development but it might be a lot of work up-front especially when you are just getting your head around it. And I've used MVVM in real/production projects, and it works like a charm - in fact, in my experience armed with the right toolset I've not met with any dead-ends whilst using MVVM, though sometimes the solution might be less than ideal.

    Hope this helps.
    Rishi

    Sunday, January 31, 2010 6:12 PM
  • Hi Jeremy,

    Thank you for your response --I'd like to mention that I appreciate reading your blog entries as well, since I frequent these forums as well as silverlightcream.com.  Anyone who takes the time to educate neophytes like me in this sea of new technology rocks in my book.

    Don't get me wrong, MVVM is a wonderful and very elegant solution if what on is developing is a simple forms-based editing application.  However, when the architect driving our development effort tells us that there should be "no code behind" except in "extreme circumstances" I scratch my head and wonder: a) why must there never be code-behind; b) what constitutes 'extreme' circumstances; and c) why aren't they forced to write some code that fits their aggravating rules?

    The frustration comes (and Mr. Dawson can correct me here) from having to data-bind to an ItemsCollection of a container that must be adapted in the background.  For example, I have a collection of Oranges and I need to create "document windows" for each orange.  I can bind to the "ItemsSource" of the document container, but exception is thrown that I cannot convert an orange to a document window type.  Fail step one.  I write a converter, based on one used for the Silverlight Tab control which takes the bound type, iterates through each element and converts them to a document window type, returning that collection.  It works to the point until I need to dynamically update the collection and I get an exception about updating an item while the item has been updated.  Heck man, adding a 'new' item to a collection of objects has never been so frustrating when doing pure Win32 or Windows Forms development.

    What really chaps me the most is that this 'architect' does not have to do any UI development at all and while they are responsible for choosing the technical direction of our company; they are; a) neither cognizant of Silverlight's limitations compared to WPF; or b) aware of the complex UI interactions required by the documentation for new products.

    Our architect chose to use MVVM and because it was mandated, it was employed in a prototype project and eventually a project that was delivered.  It took over forty-eight hours for two people to develop a Silverlight application which had pretty much four screens, one of which was the main data entry window (and used MVVM to bind its data to the model).  Based on the requirements, certain fields on the form should be 'read only' if an item was checked or if a certain text-box had information, other elements were disabled, etc.  I had to add so many properties to the "ViewModel" just to control vizualization of items based on business rules for the User Interface.

    What could have taken me four hours took over fourty hours for something so simple to do with code-behind.  I understand the separation of the user interface from the code; but not to the point where the developer is stressed creating property upon property to apply to user interface elements which reflect complex business logic in order to accurately reflect what is shown or updated in a user interface based on given requirements.  It gets to a point of insanity --why?!!  Another developer using a different platform and paradigm could have eaten my lunch if they wrote it using the pragmatic approach.

    I would never 'force' a team of developers to adopt this design pattern.  While it's great for some applications (basically form input screens), it sucks for complex User Interface manipulation.  Any person who chooses this as an absolute pattern should be forced to write UI code (along with all the complex business rules) to see just how much it sucks.  One huge class with properties out the "wazoo" to handle the enabling, disabling, hiding, un-hiding, maximizing, minimizing, changing colors based on the price of tea in China.

    At times, I wish I could just code this application in one or two weekends and show my boss *something* for those efforts.  Instead, I have to deal with this complex application development paradigm (MVVM and 'Prism') in order to just create one single coherent application which never seems to get finished due to all the "technicalities" I run into during its creation.

    Cheers,

    Joe

    Sunday, January 31, 2010 7:28 PM
  • Greets,

    This is great stuff Rishi, but it enforces my point that MVVM development is far from mature.  You have created a framework (which I hopes works with WPF and Silverlight equally), but it is a framework we are probably not allowed to use because it was not adopted by our architect.

    It sounds as if  your framework helps with UI design; however, do I really need to use another framework for the sole purpose of implementing UI updates in my application?  Sure I can use "triggers" all over the place.  Remember, I can "data bind" to an ICommand interface and attach to a button 'click'.  How do I deal with people who create new document windows, dock, un-dock, etc.  Does your framework handle 3rd party components and their events?

    I like how people want to 'de-couple' the UI from the code and I'm ok with that, I just don't think people have really thought this through all the way.

    I am also irritated that I am reduced to educating myself about some of these new technologies through blog posts and forum messages --whatever happened to good old education on something tried and true?  Show me one published book that covers Silverlight, MVVM and Prism as a viable development environment for an enterprise-wide application.

    Sorry Rishi, my anger wasn't directed toward you. :)

    Cheers

    Sunday, January 31, 2010 7:52 PM
  • Hi Rishi,

    Based on your reply:

    "Similarly, there are lots of other tid-bits helpful for MVVM style development but it might be a lot of work up-front especially when you are just getting your head around it. And I've used MVVM in real/production projects, and it works like a charm - in fact, in my experience armed with the right toolset I've not met with any dead-ends whilst using MVVM, though sometimes the solution might be less than ideal."

    I agree, it is a *lot* of work up front and my employers expect to see some results or at least some level of progress.  I would like to know what real projects you've used this in -- I have used MVVM in a *real* project and it works, works well, but it took a long time to get there, is very incomprehensible to other developers that need to maintain it.

    The right "toolset"?  Are you saying that one has to put forth a bunch of code in order to use this design pattern?  I'm also taken stumped by the statement "sometimes the solution might be less than ideal".  If you're using this design pattern, what is considered "less than ideal?" when a solution is developed.  Also, what does one consider the "right toolset" for developing a less than ideal application?

    I (and probably my employer) are still trying to get the "head around" why, even when the pattern is understood, it takes so long to develop an application.  If you can tell my employer it's because: a) I can't get my head around it; b) I'm not using the right tool-set; and c) I don't code for less than ideal solutions, then you might win me over.

    Cheers.

    Sunday, January 31, 2010 8:07 PM
  • Saw this thread on Twitter and decided to weigh in.

    From my perspective, as someone whose focus is data driven applications, I find it important that communication between the View and the Model go through the ViewModel. I also find it important that, as much as possible, the communication between the View and the ViewModel should be done without involving code behind. Finally, if something can be done easily using binding to the ViewModel then that is where the code should be. If I were architecting your system, that is what I would require. Beyond those three restrictions, you could put as much code in your code behind as you want.

    An example?  Ok, Let's say I have three input boxes on a form along with one check box.  If the check-box is checked, then two of the textboxes are disabled, but not if someone entered text into the first.  I can't do this with traditional even handling, instead, I have to add a new assembly to my references to get commanding and add more mark-up to my XAML.  In some cases, I can't even use 'commanding', because I need to watch for other events.  Gee, it would be nice if life were distilled to more than a simple "button click", but apparently the original designers had no vision beyond that.  (The Expression Blend team, however, had better thoughts.)

    Not sure why you need commanding for that. You bind the three textboxes (twice, once for the value, once for the disabled) and then bind the IsChecked of the checkbox. You put the logic to determine the disabled state within the Disabled property that the textbox is bound to and you simply raise the PropertyChanged for them in the change of the IsChecked property. That is the kind of easy to maintain, easy to read code that I use MVVM to get.

    Sunday, January 31, 2010 8:09 PM
  • Colin,

    Again, if I were developing an application that was a simple 'form' editor, I would have not qualms against using the paradigm.  However, if the application requires some complex user interaction, is it really necessary that I create a ton of behaviors in order to hook up events to objects when I could just hook up to their events directly?

    Sure, one could argue that the code would be 're-usable', but you have to admit, how much "business logic" for a single user interface is actually re-usable?  Sure, individual components such as button, list-boxes, combo-boxes, etc. are re-usable, but when it comes to a complex form composed of the aforementioned, how many times have you re-used it?

    Now for the 'commanding' example.  UI requirements dictated that something should be enabled or disabled based on what a user typed in a box.  Ok, easy enough, but in Silverlight (and possibly WPF) the ViewModel wasn't updated with information until focus was lost in the edit box in which the user was typing.  They didn't like that the UI wasn't updated until the user lost focus from a particular control.

    Ok, there goes the "Click" command and the checking in the ViewModel, instead, I have to wire up my own MVVM compliant "event handler" so that I can get a "Key Up" command in order to then check the length of a string in a text box to then delegate to a property on the ViewModel which returns a 'true' or 'false' value for the purpose of enabling or disabling some other control.  Note that Silverlight is a very rich client model, it interacts with the user through their browser in ways traditional Web applications do not.

    For complex user interface decisions, MVVM falls on its face and forces a programmer to do more coding than necessary; for a simple form-editing application, it's a great tool.  Some coders need to get their head out of the clouds and realize that people using applications aren't just filling out forms and hitting a submit button (like responding in a forum).  One day, the business rules decide a UI element must be enabled or disabled; what happens?  Great, throw another property onto your ViewModel.  This is the heaviest part of your application and is probably so specialized you really don't care to re-use it for something entirely different.  Congratulations for finding a creative waste of time.

    I would love to see how applications such as "Visual Studio 2010" use entirely no "code-behind" but instead is all "XAML" driven using the MVVM paradigm.  In the end, it is *all* code-behind, it's just structured in a way that makes it more confusing to use or for that matter, re-use.

    Thank you for the input, it gives me a bit more to chew on.

    Regards,

    Joe

    Sunday, January 31, 2010 8:54 PM
  • One more thing Colin, I'm enforced to use this paradigm with Silverlight.  I guess you're probably a WPF developer who has access to more creature comforts than one who has said restrictions.  Silverlight 3 added the ability to bind to other UI components, but it's still far from WPF in many respects and requires a lot of work to do simple tasks while being forced to use MVVM.

    Cheers.

    Sunday, January 31, 2010 8:58 PM
  • Exactly as you say, using MV-VM fully is far too difficult for complex scenarios. But, you could use your own way there, have a Model that saves the state of the UI, do complex operations in the UI itself like drag/drop etc., It's more like MV- pattern, in which it only has a model to deal with the state of the UI. This comes in handy if you have multiple UI's sharing the same state. It keeps UI + UI Behaviors in one piece, and the Model in the other piece. -Fahad
    Sunday, January 31, 2010 10:39 PM
  • Show me one published book that covers Silverlight, MVVM and Prism as a viable development environment for an enterprise-wide application.

    First, thanks for the kind words and feedback. I appreciate you!

    I think the reason you don't see the published books right now is simply because the technology is moving too fast. I know some people who were writing the Silverlight 2 book on "xyz" when it became Silverlight 3 and had to jump back to the drawing boards to finish it to get it out in time before Silverlight 4. I am happy Silverlight is moving so quickly because it will get to a mature level far more quickly, and it's not iterating "just to iterate" but is in fact accomodating developer feedback and integrating these features into the core framework. If you take a look at Silverlight 4 (which I know and understand is not a luxury when developing commercial software, the beta is always "the future") you'll see a lot of issues and problems addressed in the core tooling.

    However, I also just wanted to post and say, "Keep your eyes open" because there are a few books in the pipeline that will be released soon which do cover the architecture and models for Silverlight. So they are on their way and will be here soon.

    Monday, February 01, 2010 7:29 AM
  • One more thing Colin, I'm enforced to use this paradigm with Silverlight.  I guess you're probably a WPF developer who has access to more creature comforts than one who has said restrictions.  Silverlight 3 added the ability to bind to other UI components, but it's still far from WPF in many respects and requires a lot of work to do simple tasks while being forced to use MVVM.

    LOL, sorry my comment that I followed Twitter here must have given you the wrong impression. I have never actually written a WPF application, I went directly from ASP.NET to Silverlight. Also, for future reference, if someone has at least two diamonds under their name on the Silverilght forum then they are probably using Silverlight.

    Now for the 'commanding' example.  UI requirements dictated that something should be enabled or disabled based on what a user typed in a box.  Ok, easy enough, but in Silverlight (and possibly WPF) the ViewModel wasn't updated with information until focus was lost in the edit box in which the user was typing.  They didn't like that the UI wasn't updated until the user lost focus from a particular control.

    Yes, I see, you are in a particularlly difficult situation. You have an architect that is enforcing the extensive use of the ViewModel while also requiring the UI to work in a way that it wasn't designed to work. That is a bad combination and I can understand your frustration. To me, most of the reason for using MVVM is to work with how the controls work. It isn't really about testabliity or reusability, it is about using the natural binding mechanism to write code that works better as is more easily maintained. Testability and reusability are nice but as far as I am concerned they are just bonus.

    MVVM is a pattern, and like all patterns sometimes it applies and sometimes it doesn't. Maybe your architect is trying to force the pattern in a situation where it doesn't apply. I can't really know that, however I can caution you not to repeat the same mistake that you are accusing others of making. Don't generalize your problems onto everyone elses situation, everyone has different design considerations.

    Monday, February 01, 2010 10:16 AM
  • Jason, you've raised some good points, let me address them in a question/answer format for convenience sake:

    Q: When to use the code-behind?
    A: My golden rule is this, don't let view-specific details leak into your ViewModel, unless of course the View details are the Model itself. Now, to follow this I first try to use existing infrastructure/tooling like binding, behaviors etc, if that is not possible then I try to create custom behaviors/triggers/actions per the need, and if that is not also appropriate then I use code-behind. That is a simple enuff workflow?

    Q. You have an Orange object and you want to visualize it as some sort of Document Windows?
    I need more specifics, but it seems to me it is appropriate to hold the Orange into a "Document" object, and then the open/closed, docked/undocked state etc will be encapsulated in the Document object rather than leaking your business model (the Orange object). To use the document, you will expose it as an observable collection, which you can bind to the Tabs collection. Have a look at Calibrum it has pretty good guidance around such issues. Couldn't resist this, don't try to make apple juice out of oranges :)

    Q. About adopting nRoute?
    First, nRoute for now is SL only - and in case you are not be able to adopt it as a whole, you have the source code so pick and choose the stuff you need. I say, no need to reinvent the wheel. Also nRoute is not limited to UI related stuff, it has a lot of infrastructure related features - likes services, modules, event-aggregators, view-models, MEF like framework etc. And it has a lot of unique features that really realize MVVM, do look at some of the sample projects on Codeplex as plenty of are non-trivial.  

    Q. About "lots" of up-from work?
    What I meant by that was you have to on the onset divide your application's functionality between Views, ViewModels, Services, or ViewServices etc. And that is what gets people I suppose, but once you are used to it, it is not really that big of a deal. I perhaps have a perfect example for you, I took this Sudoku game (by Lee Saunders) which was essentially implemented in the code-behind, and in a step-by-step fashion I carved a MVVM application out of it. And you have both the pre and post MVVM code-sets available to look at, along with an accompanying blog post that show how to transform it to MVVM:

    Pre-MVVM Sudoku Info: http://oldschooldotnet.blogspot.com/2009/03/sudoku-in-silverlight.html
    Post-MVVM Sudoku Info (using nRoute): http://www.orktane.com/Blog/post/2010/01/23/iPhone-Sudoku-in-Silverlight-using-MVVM.aspx

    Note, both the implementations rely on the same engine to generate the Sudoku puzzle. And, after you have gone through it, consider in which code-set will it be easier to implement a new feature (like pencil marking) that has been requested of me. Also, mark on the clarity and testability of the code if you can.

    Q. About using a toolset for a design pattern?
    Design patterns are implementation-agnostic, that doesn't mean for a specific implementation you can't use a toolset - hell, .NET framework is a genormas toolset. And also I often find people think whatever Microsoft delivers is the only starting point for your application, well breaking new, it's not always appropriate - especially for less matured technologies like WPF/SL.

    Q. About things being less than ideal?
    Yes that is true, less than ideal solutions do turn up, but it has more to do with the limitations of SL than the MVVM pattern - and till now I've only had 3 or 4 such situations which is far from tainting the whole situation as flawed.

    Q. About getting your head-around?
    I think for a lot of people (including me) there is a light-bulb moment for MVVM, when you reach that the your head-and-tail will be all around it, don't worry :) For a recent case in point see http://blogs.silverlight.net/blogs/jesseliberty/archive/2010/01/28/mvvm-it-s-not-kool-aid.aspx

    Q. About the books?
    I've heard on twitter couple of people thinking about writing MVVM books - Shawn Wildermuth was the most recent of those, tell him if you want one. But for myself, I like to live on the blogging-edge, it's more upto date and interactive than any book can be.

    Oky, this is getting long let me leave it here - and don't worry about directing it onto me, it's a good learning exercise.

    Rishi

    Monday, February 01, 2010 11:59 AM
  • To me, it sounds more like you have a problem with your boss/architects/job/etc than with MVVM (or what they told you MVVM is). MVVM is a pattern, just like an observer pattern or factory pattern. None need standardization. No implementation looks exactly the same. If the pattern is not helping, you either a) used it when you don't need it. b) using it incorrectly. In any case, you've had this problem for over five months (http://forums.silverlight.net/forums/t/127825.aspx), maybe time for a new place to work?
    Monday, February 01, 2010 7:37 PM
  •  comment that I followed Twitter here must have given you the wrong impression. I have never actually written a WPF application, I went directly from ASP.NET to Silverlight. Also, for future reference, if someone has at least two diamonds under their name on the Silverilght forum then they are probably using Silverlight.

    I apologize for making that assumption (this is a Silverlight forum after all, doh!) --I have seen many posts or blogs using this pattern and it seems that due to richer data binding capabilities in WPF that it is easier to use the pattern with WPF than it is with Silverlight.  In some cases, to do something simple required creation of custom behaviors to hook up "non-click" events (such as when text-box text changed) on a user or custom controls.  It seems that some of the most re-usable and encapsulated code using code-behind for simple components now requires speciallized attached properties and other trickery just to adhere to the pattern.

    Yes, I see, you are in a particularlly difficult situation. You have an architect that is enforcing the extensive use of the ViewModel while also requiring the UI to work in a way that it wasn't designed to work. That is a bad combination and I can understand your frustration. To me, most of the reason for using MVVM is to work with how the controls work. It isn't really about testabliity or reusability, it is about using the natural binding mechanism to write code that works better as is more easily maintained. Testability and reusability are nice but as far as I am concerned they are just bonus.

    MVVM is a pattern, and like all patterns sometimes it applies and sometimes it doesn't. Maybe your architect is trying to force the pattern in a situation where it doesn't apply. I can't really know that, however I can caution you not to repeat the same mistake that you are accusing others of making. Don't generalize your problems onto everyone elses situation, everyone has different design considerations.

    Fair enough... and yes, it is a difficult situation.  Now, I have worked on one project which was basically nothing more than a glorified form for submitting data.  There were a handful or rules on updating the user interface based on certain items being checked, certain textboxes containing content, etc.  It took a bit of fiddling to make sure property notification and validation was working correctly, but it is a case where I thought the pattern was elegant.

    However, when required to use this pattern just about everywhere, I'm finding that it doesn't work for everything and when the person mandating that these rules be followed, running into such difficulties where that pattern clearly does not fit are usually met with a "there has to be a way to do it" response.  I spend more time trying to find a hack to make it to work (if there is one) then actually getting the job done.  I hope the MVVM support for Visual Studio 2010 will help standardize the use of the pattern and provide more tools to have to write less code.

    Regards,

    Joe

    Tuesday, February 02, 2010 6:41 AM
  • To me, it sounds more like you have a problem with your boss/architects/job/etc than with MVVM (or what they told you MVVM is). MVVM is a pattern, just like an observer pattern or factory pattern. None need standardization. No implementation looks exactly the same. If the pattern is not helping, you either a) used it when you don't need it. b) using it incorrectly. In any case, you've had this problem for over five months (http://forums.silverlight.net/forums/t/127825.aspx), maybe time for a new place to work?

    Actually, it's more a problem with having to find ways to make the pattern fit for the sake of using less code behind.  I agree with both (a) and (b) above --however, it was an architectural decision to have no code-behind in any Silverlight or WPF development unless it is an extreme case.

    The problem has existed for quite some time now, but then again, I've been working off and on with different projects.  One such smaller project I was able to use the pattern (and actually complete the project), while it seems an elegant solution, it also took probably as twice as long as I had expected.

    Now I'm on a new project which combines MVVM and Prism, uses 3rd party docking windows requiring use of a fairly dynamic user interface.  It seems like it would be almost intuitive to have a collection of documents and bind them to a collection of DocumentWindows, but alas, that just doesn't work.  So now I've got to look into providing a service for the purpose of dynamically injecting them.

    The one main draw that I can see is that in an application with many views, I can create different views and viewmodels and split up the tasks among several people --however, tying that all back together seems to be quite the challenge in such a disconnected system.

    I don't need a new place of work, what I would prefer is to have some more insight as to how to appropriately apply this pattern and when and how to perform certain tasks using this technology without having to face a new frustration each day trying to get some seemingly simple functionality to work.

    You're right, no implementation looks exactly the same and there are times it is difficult to find an example that applies to how I need to use the technology.  A good number of examples I run across don't necessarily fit with the requirement I am trying to fill.

    Cheers.

    Tuesday, February 02, 2010 6:58 AM
  • I admit I'm still new to MVVM and leaning as well. I think at this point of time, it's still too early to see the benefit of using MVVM.  From first look, it is simple and elegant, that's exactly style of coding I'm always after. But when I tried to write it, even just for a simple data entry application which is considered the most suitable for MVVM,  I found it's just not that easy.  I'm still struggling with a lot of things I want to accomplish.

    I was reading Jessy Liberty's MVVM-It's Not Kook-Aid blog (http://blogs.silverlight.net/blogs/jesseliberty/archive/2010/01/28/mvvm-it-s-not-kool-aid.aspx) and learnt how to use Interaction.Triggers to bring back the event to the ViewModel. With the Trigger.CallDataMathod set to a function in the ViewModel, I can catch the event on the UI and act upon it in the ViewModel.

    A good example is in Jessy's sample, a ListBox selection changed, so I can do something on that selected Data. All the ListBox, ComboBox are inherited from System.Windows.Controls.Primitives.Selector, so in the EventHandler function in the ViewModel I can cast the sender to a more generic Selector, get the SelectedItem.

    Good, I was trying to figure out exactly how to do this. But in my case, I used DataGrid as Selector (or a DataForm could also be replaced here as Selector), I can not cast them to Selector. I had to know what type of control as the event sender in order to get the SelectedItem(in case of DataGrid) or the CurrentItem (in case of DataForm),

    But I thought the ViewModel should know minimum about the UI on the Page. I have a class library project for my ViewModels only which I didn't think I should have to reference many Control libraries (except maybe just the basic System.Window.Controls). Apparently I was wrong.

    I could separate UI related code in the page’s code behind, and non-UI related code in the ViewModel,  But that would make maintaining the code even harder.

    Just my 2 cents.

     

     

     

     

     

    Tuesday, February 02, 2010 2:40 PM
  • It's a good two cents, and I appreciate it. However, I think a lot of people confuse "different" with "difficult." Once you master MVVM, it's not difficult at all and you don't have to shoot through hoops. Like transitioning from procedural code to object-oriented code, transitioning from older models (heck, most people didn't have a robust architecture and just slammed data readers into combo boxes because that's what the examples did) like control-controller, etc, to MVVM requires changing your way of thinking and really understanding the databinding model and hierarchy.

    Your view model doesn't have to know a thing about your view.

    For example, let's assume you have a list of Widgets and want the currently selected Widget. Many people feel they have to somehow tap into a selected item changed event or something similar, which means the MVVM knows about the UI element or there is code-behind.

    In reality, it's as simple as having a Widgets list and a current Widget on your view model:

    public ObservableCollection<Widget> Widgets { get; set; }

    public Widget CurrentWidget { get; set; }

    Then binding the list box appropriately:

    <ListBox ItemsSource="{Binding Widgets}" SelectedItem={Binding CurrentWidget, Mode=TwoWay}"/>

    Then you are fine and the view model doesn't care.

    You can also nest view models and have other patterns.

    I've been writing some fairly large and complex Silverlight applications with very heavy logic, and have yet to find a place where MVVM didn't fit well. I also don't go through hoops and try to create exotic patterns just to accommodate UI behaviors ... if there is an animation I need to fire or something UI specific, rather than spending a day extending my ViewModel for some abstracted behavior that will fire the UI event, I simply put a code behind event where a code-behind event makes sense.

    I don't think code-behind is appropriate for moving data at all. However, it is absolutely approrpiately in my eyes to use code behind for a user control to manage the visual state and elements of that control ... that is keeping the UI logic in the UI layer, and is far better in my opinion than dragging it down to the view model.

    That's my 1 1/2 cents.

    Tuesday, February 02, 2010 2:51 PM
  • Your view model doesn't have to know a thing about your view.

     

    Yes, that's exactly what I thought. Then I guess the Trigger.CallDataMathod should take a parameter I can pass back which should be the current selected data, not the event sender. In the ViewModel I do not care what happened on the UI as long I have the Data I can act upon. 

     

    Tuesday, February 02, 2010 3:05 PM
  •  

    public Widget CurrentWidget { get; set; }

    Then binding the list box appropriately:

    <ListBox ItemsSource="{Binding Widgets}" SelectedItem={Binding CurrentWidget, Mode=TwoWay}"/>

    I see what you mean now. I don't need the Trigger at all. Thanks!

    Tuesday, February 02, 2010 3:09 PM
  • Hi all,

    looking for information on MVVM, I came across this post and couldn't resist adding my two cents ;-)

    When that whole MVVM thing came up some time ago, I was quite sceptical - I thought it would be too complicated, too much overhead etc. etc.. Actually I perceived MVVM as just another complication of MVC, probably puzzled out by some geek who had never actually experienced real-life software projects.

    However, after digging into MVVM for a while, especially in a Silverlight context, I changed my mind completely. By now I consider it the state-of-the-art development pattern for WPF/SL applications. The reasons:

    1) MVVM gives you all the advantages of properly implemented MVC, i.e. separation of the UI from the rest of the application, clean business data models etc.

    2) It adds a clearer, common terminology & guidelines that are more specific than MVC and therefore help prevent "dirty code". Additionally, the fact that MVVM is in some way built into WPF (Commands, DataBindings etc.) makes it easier to explain to developers new to this topic.

     BUT:

    I do not understand why people actually try to get rid of all code-behind in the view. I agree pretty much with Jeremy:

    if there is an animation I need to fire or something UI specific, rather than spending a day extending my ViewModel for some abstracted behavior that will fire the UI event, I simply put a code behind event where a code-behind event makes sense.

    I don't think code-behind is appropriate for moving data at all. However, it is absolutely approrpiately in my eyes to use code behind for a user control to manage the visual state and elements of that control ... that is keeping the UI logic in the UI layer, and is far better in my opinion than dragging it down to the view model.

    This is exactly the point. In my opinion, code that is solely view-specific should reside in the view, and nowhere else. So not only would I say that trying to get rid of all UI code behind is both cumbersome and unnecessary; I would even say that it can be counterproductive. Let me explain: One reason why MVVM is so cool is that the UI is separated from the rest of the app, which means that it becomes exchangeable. You might ask, why would I want to exchange the UI? I only have one UI in my app and tha UI will never change anyway. Well, from a business perspective, i.e. the business processes that the UI resembles, there may actually be only one UI, but there might be e.g. different UIs for WPF and Silverlight. Or different UIs for Silverlight on a desktop machine vs. Silverlight on a mobile device.

    Now, if we would try to handle things like Drag & Drop in the ViewModel instead of the View code behind, we would create a logical coupling between the ViewModel and implementation-specific details of the UI. Which is bad. Because there might be a second UI, e.g. for mobile devices, that might use a different technique for treating data instead of Drag & Drop. What matters in the ViewModel at the end of the day is not that some data has been dragged & dropped somewhere; what matters is the logic behind that user interaction, e.g. choosing an item of data out of a collection of data items, which may also be accomplished by other means, e.g. using a list view. Therefore, in my opinion, it would be a lot cleaner to handle such UI implementation-specific things, like Drag & Drop, in the UI code behind and translating them into "logical" actions, i.e. commands.

     As I said - just my two cents ;-)

    Cheers,

    Alex

    Tuesday, February 16, 2010 10:28 AM
  • absolutely agree, personally I would not touch MVVM with a barge pole. The reasons are:

    1. Much more complexity, one new non-standrad additional layer

    2. You need to hook MANUALLY a lot of events, which are hooked for you in the standard code behind implementation, not to mention UI is on seprate dispatcher thread, very problematic if you have any async coming back.

    3. Logic and classes scattered all over the place, ReSharper guys are happy you will need a specila tool in order to follow it.

    4. Why the h..l I read all the time that MVVM improve the maintainability of the code?!? Common, I mean if you have thousands of lines more code and new layers and a lot of new libraries referenced just to make the thing move an inch, and actually Domain model is making the business logic scattered across hundreds classes, what really improves maintainability is Service Model and standard code behind UI.

    5. Some operations are tricky, try set focus :-)


    Yes I am the architect you have mentioned in the post and I never will design an enterprise solution based on MVVM or any complex pattern, just because somebody has written a book about it.


    MVVM is a significant architectural investment that introduces A LOT OF complexity.

    Here is the number 1, 2 ,3 and 4 for my architecture designs:

    1. Simple, smaller the code base the better
    2. Anything that can be auto-generated should be auto-generated, MSDeploy, MEF, Unity, WCF Data services, REST, JSON yes, MVVM don't think so.
    3. Continous Integration based on rule 2
    4. Standard code, components
    5. Simple, Easy to understand and maintain code - means the business logic is on one place not scattered in hundred classes - any new developer should be able to start developing new code 1 hour after seeing the application for first time.

    In the big picture the UI is just one layer, let it go guys. Not to mention that the standard Microsft UI implementation sepration with XAML is pretty good for me. We have there a view (XAML) and we have the controller (the code behind). The model can be autogenerated so I do not see why such fuss trying reinvent the wheel ok?

    cheers

    Valko

     

     

     

    Thursday, May 20, 2010 4:28 PM
  • Very good discussion on both sides. I have to agree that MVVM is an overblown unnecessary pattern. I see the strengths of it but I'm sorry the bang for the buck is just not there. 

    Monday, May 24, 2010 2:37 PM
  • I don't agree at all that it is overblown or unnecessary. I certainly see people abusing it, or claiming it is something it's not. If there are better methods for what you are working with, that's great, stick with them. Makes no sense to follow a pattern just for the sake of following it. I'm not trying to sway your opinion as you've obviously found a workflow that doesn't use the pattern which is successful for you, that's great.

    For those reading this, however, there are plenty of projects that found success with the pattern. I wouldn't have completed many large, recent projects without it. Our company has used MVVM in several large projects and received incredible "bang for the buck." We're just able to build it faster, more robustly, scale the teams, etc. It's one thing for smaller projects with only a few Silverlight project files or a few development members. When you're working with dozens of projects and several developers, the separation of concerns that comes with MVVM is phenomenal.

    It also makes a difference depending on how your design works. If the developers are also designers, or if you have a traditional "back and forth" approach where the designer tosses it over the fence, the developer integrates, then tosses it back, etc, then I can see some of the frustrations.

    However, when you have a full design team working in parallel with the development team, again MVVM facilitates this workflow and makes it very possible to scale out the workload.

     

    Monday, May 24, 2010 3:00 PM
  • I know I'm late to the party but I just wanted to say I loved this thread. I'm working on a very hefty Silverlight project which is designed to help users build casual games. There are at least a dozen modal dialogs bound to ViewModels, and some dialogs can add entities which must be immediately reflected in other dialogs.

    I'm trying so, so hard to stay true to all the MVVM rules that have been stated so vehemently around the web. But I'm not gonna lie, the only time my frustration goes through the roof is when I'm having trouble forcing things to work in the MVVM pattern. Sure, at the end of the day I might have "separation of concerns" but I also have 25% less hair on my head and 150% higher blood pressure... and I'm not even sure I have less code than I would've had with code-behind.

    With SL4 things have gotten a little better with the built-in Commanding support on buttons, but today I discovered that I need similar commanding support on ListBox_SelectionChanged. I did a quick search and found that there's apparently no direct support for this right now and that I'd need framework XYZ from CodePlex. Don't get me wrong, I love the work Devs are doing on CodePlex but every time I learn that I need an unfamiliar framework to achieve something "simple" my heart sinks a little more. I don't want to babysit unfamiliar frameworks for the rest of my project's lifetime. It's especially frustrating when I remember how quickly SL versions are flying out the door, so by the time I finally get comfortable with one approach — especially with stuff like Commanding — it's gonna change before my project's even finished. It's discouraging to say the least.

    So long story short, I'm going to cheat. I'm going to add code-behind for ListBox_SelectionChanged that calls a method on my ViewModel. I guess I'll have to live with the guilt of being a rulebreaker, but I have a feeling I'm saving myself a lot of pain in the long run.

    Sunday, October 17, 2010 7:19 PM
  • Why not just use the available event trigger that ships with Blend? You can either use it from Blend, or if you don't have Blend, use it from the Blend SDK. It allows you to lock into any trigger whatsoever - including selection changed - and then invoke a method or command and pass whatever parameters you like. Isn't this what you're looking for? It's drag-and-drop in the designer to attach it to a list box.

    Of course, if you are only allowing selection of one item at a time, you don't even need that. Just bind the list box to the list of items, have a property that is the selected item and bind the Selected Item as a two way binding. Anytime the property changes, do what you need - that's the same as "selection changed."

    I do agree, if you are "forcing it" to work with MVVM, you're doing it wrong - some things are perfectly fine in code behind. However, a lot of times I see people just not knowing the patterns to solve the problem - it's not that it's not easy to solve, it's just that it's not well illustrated/documented to do so.

    Sunday, October 17, 2010 7:27 PM
  • Hmm, I assume you're referring to CallMethodAction and InvokeCommandAction? I just played around with CallMethodAction and yeah, that was pretty simple. It looks like I need to set up a delegate command of some sort w/ InvokeCommandAction if I want to pass parameters around, but I'll figure that out.

    But anyway, yes, your last few sentences get to the heart of the problem. I tried to search on something like "MVVM Commanding Silverlight listbox" and it was an absolute maze. Every article needs to be checked for 2009 vs. 2010 right off the bat because Commanding has been in such a state of flux in just one year. Then there are articles that seem to be extremely over-engineered for the exact problem I was having -- one which you just solved by nudging me toward something very simple. 

    Sunday, October 17, 2010 8:42 PM
  • There are developers who frustrate themselves trying desperately to get everything to fit in with whatever the pattern of the day is, sometimes ending up with something "elegant" and sometimes not.

    And there are developers who Get Things Done and ship software.

    Monday, October 18, 2010 3:55 AM
  • I also have to vent my anger.!!!

    Why are there so many books that go for the "dummies" approach? They cover alot of ground but THEY never go anyplace?

    Their needs to be more books that "concentrate" just on one area and do it correctly.

    Let's take a look at what is neccesary to understand data in silverlight

    1 WCF 

    2 a good n-tier silverlight book data services cookbook is a good book however it is only a starting point

    3 Unfortunately, I have never seen anything really challenging the developer!!!!

    THe basic problem with all these books is they give you hints but they never take it above any intermediatary level

    What I would like to see is one publisher use a building block approach...   algebra 1 algebra 2 etc etc

    silverlight applied to a  basic n tier library then apply a mvvm model then use prism.

    Their are some authors that write 200 pages on this stuff(too lightly) and yet the public is expected to like this mediocre work...Why don't authors find out what the public wants.??? Perhaps I am asking too much as far as data is concerned

    and maybe someday a publisher (will follow a detailed approach  like beginning silverlight  data

    building silverlight toolkits using mvvm and class libraries and then let's build prism. It's very sad most authors do not have a clue what people want. I did see one publisher  is building a reporting  book  on silverlight 5 reporting  and  beginning silverlight  5 business applications Let's hope they remember on how to build A SILVERLIGHT CLASS LIBRARY and show the proper on how to use a class library. hint model,  data services, at least pete brown's book mentions this....     

    which is a good start however book companies need to look at these books as a series on these subjects INSTEAD OF ONE BOOK because one book never seems to be adequate. Silverlight books on data need to become "Enterprise friendly" I hope many people feel the same way I do...    

    I personally am very disappointed in many silverlight books....THank you for letting me get angry....

    and By the way Prism books are based on patterns. WHY doesnt someone apply these patterns in a book???

    Most authors need to think Enterprise!! I hope other people feel the same way I do....

    Wednesday, June 15, 2011 3:23 PM
  • I posted this on another thread, but IMO, this discussion, while important, misses the real place where MVVM should be implemented.  Here's what I said.

    "BTW, here is what should be the #1 request for Silverlight, WPF, or Jupiter... Implement MVVM

    If your view is truly decoupled from your view model, then why do we EVER see blue balls? The view should display almost instantly! Even HTML does this more effectively than Silverlight.

    That single change would have made Silverlight a clear winner. Ok, I understand that Silverlight came first, then MVVM got popular, but once you see the problem, you need to fix it."

    Can anyone tell me why we have to wait for the logic to load before we can see the XAML View?  And yes, I know about splash screens, but they wouldn't be needed if MVVM was actually part of the system.

    Friday, June 17, 2011 5:49 AM
  • I also have to vent my anger.!!!

    Why are there so many books that go for the "dummies" approach? They cover alot of ground but THEY never go anyplace?

    The publishers have an easier time selling a "dummies" book then a more targeted book. The problem with creating a commercial book is that the more complex and advanced you get the more of your audience you lose. Every time you make a decision you reduce your potential audience and if you go to far with that there is no way your book will end up on a shelf at Barnes and Noble.

    To be perfectly honest, advanced books don't sell very well. Beginners don't want them and advanced users don't need them. I am hoping that Mike Brown's upcoming MVVM book breaks that trend.

    Friday, June 17, 2011 10:21 AM
  • colin,

    I would love to find a good mvvm book and then use design patterns with this book  It would be great to see an enterprise book !!!l I  hope mike brown's book , on MVVM,  tries to accomplish those goals. A long  prism book would be great!! No one really wants to touch this, it's too bad...   silverlight writers should be more in touch wit their audience.       

      I  saw packt had two book coming out for silverlight 5

    Azure in silverlight and  another mvvm book by Ryan vice. My favorite silverlight 4 data books Pete brown's book-silverlight 4  in my opinion was the  best book for mvvm

    2 good starting book  silverlight4  cookbook gil cleeren  and

    and pro silverlight business(It should be called beginning silverlight business)  by chris anderson why dont books use wcf library?

    I also own john papa's book  

      They are just a starting point

    I am trying to learn event aggregator(Publish-subscribe) for prism using dependency injection  (mediator pattern? Do you have any ideas?  Thank you for your help ) Please realize  I just hate the idea of a service locator

    I want to use child window for authentication and I have been searching for a good example . I want to accomplish using prism, wcf ria class library, intrigued by EF code first-hopefully this gets released soon from the wcf ria team. Colin I  really hope for great things in the future  for silverlight!!        

    Sunday, June 19, 2011 5:25 PM
  • I wouldn't have completed many large, recent projects without it. Our company has used MVVM in several large projects and received incredible "bang for the buck."

    Jeremy would you mind being more specific?  What - specifically - were you able to do with MVVM that you would not have otherwise been able to do?

    I'm still just learning MVVM but honestly I'm skeptical.  Nowhere have I seen a specific list of values that may be achived via MVVM that would otherwise not be available (or achievable at a much greater cost).  Indeed, it seems to be the other way round.

    Here is a classic example from stackoverflow:  Why MVVM and what are it's core benefits.  This is the classic party line that I see again and again.  I'm not saying it's not true - I am saying 

    a.) the arguments are very general 

    b.) I don't see where I get anything that I don't already have,

    c.) I pay a lot in terms of time/complexity for what I get and I don't see where what I get has has immediate value

    d.) I don't see how the pattern solves any more problems than a well architected n-tier design.

    Example from the above cited post: First off, the key benefit is enabling true separation between the 'View' and 'Model'. What that means in real terms is that if/when your model needs to change, it can without the view needing to and vice-versa.

    This argument, the "key benefit" by the authors own words, meets all of the four criteria I stated above.  I won't go through point by point but it's arguments like this that make me uneasy.  I'm not taking a stand against mvvm I just want to see some factual evidence that it really does provide more bang for the buck and that the bang is of immediate use.

    Sunday, June 19, 2011 9:22 PM
  • Its not always easy to keep view logic out of the viewmodel, but I've found that data binding (converters included) and command binding is doing its job very well for me.

    So here's a way to make it easier to get view code out of the viewmodel when you have a command that needs to tell the interface to do something: define a delegate type in the viewmodel that is designated to hold a delegate that will perform the UI action. When the viewmodel is created by the view, assign to the UI delegate property of the viewmodel.

    My example, where I have actions that are performed in a pane that is required to close when a command is executed:

    public delegate void CloseAssemblerDelegate();
    
            public CloseAssemblerDelegate AssemblerCloser { get; set; }


     

    So when the ViewModel does a command that requires that the pane to close, it just calls AssemblerCloser();

    Here is where I assign it in the view

    Views.AssemblyView pane = new Views.AssemblyView();
                pane.DataContext = new ViewModels.AssemblyViewModel(selectedEPolicy, pane.browser.Dispatcher, delegate()
                {
                    PaneGroup.Items.Remove(pane);
                });
                PaneGroup.Items.Add(pane);


     

    Tuesday, June 28, 2011 4:25 PM
  • MVVM is designed for companies with LARGE budgets that can afford "teams" (more than 2 or 3) developers and graphics people working on a single project.

    I gotta ask a few questions here:

    1.  How is that cost effective for a company ($11,800 per head in MSDN license and about 100K - 200K per developer)?

    2.  It's slow because of the excessive amount of coded generated and needed to implement MVVM, why is so much setup code needed including the autogenerated code?

    3.  Entire NEW ways of developing seems to be the "soup of the day" concept that really only keeps Microsoft internal departments busy (and those book writers) -- why is there no thought put into migration of existing applications?

    4.  Developers are not adopting Microsoft tools in mass because Microsoft keeps re-inventing the same wheel over and over rather than sticking with one wheel and evolving it -- why can't Microsoft produce an evolution of a product?

    Microsoft's response is usually:

    a.  "well you're doing it wrong" (the righteous way)

    b.  "why would you want to do that?" (apprently only Microsoft is qualified to solve a problem in a specific manner)

    c.  "it could make Microsoft's platform look bad" (don't even know where to start with that one)

    d.  "this may not fit your needs"

    e.  "use this approach for new projects not migration of existing ones" (my favorite, and that helps how?)

    I honestly don't know where Microsoft get their feedback from (I've tried and got the usually thank you, case closed) -- they clearly don't listen or they listen to only a select few they believe are "in the know".  Well maybe, just maybe, those select few are wrong ... since platform adoption in a decisive market share has NOT happened yet -- it could be very possibly that Microsoft are just relying of the wrong input and not discovering what rapid business application developers want.

    I've been coding for 30+ years (pre-MS DOS days) and to this day, Microsoft has NOT successfully speeded up the process of developing business applications.  Sure, toss more developers at a project and you'll get the product done sooner (no secret formula there) ... but this has NOTHING to do with separation of UI from middle tier from back end ... in many companies it's the same developer, it's a more rare situation that companies can afford huge teams of developers, yet we have all this code bloat to thank for this separation of tasks.

    Code bloat -- Microsoft invented it, developers don't want it.

    Rob

    Wednesday, September 07, 2011 3:11 PM
  • Code bloat -- Microsoft invented it, developers don't want it.

    You've got to be kidding. Here's a little project for you. Go to SourceForge and pull down just about any Java or C++ project, and port it to WPF or Silverlight. I've done this several times, and the end result is that the C#/XAML code is significantly smaller and WAY cleaner. Code built upon archaic platforms lacking binding and standard event routing (Java/C++) end up passing references around EVERYWHERE. I don't know how many times I've seen core modules for handling something like game logic holding a reference to a screen widget. Yes, some of this is just bad architecture and bad programmers, but this almost ends up being inevitable on archaic platforms.

    If you don't like MVVM, don't use it. Just don't kid yourself into thinking that those of us who "get it" aren't seeing HUGE productivity gains or that we're using it "just because it's the latest cool trend."

    BTW, in regards to where Microsoft gets their feedback. Here's one place:

    http://dotnet.uservoice.com/forums/4325-silverlight-feature-suggestions

    Right behind "More platforms" is "Full Databinding support" Clearly there must be a lot of us that really like this style of development.

    Wednesday, September 07, 2011 3:38 PM
  • Go to SourceForge and pull down just about any Java or C++ project, and port it to WPF or Silverlight. I've done this several times, and the end result is that the C#/XAML code is significantly smaller and WAY cleaner.

    Sorry, don't have time to do that, don't really have time to respond to you, but in the name of hoping Microsoft do eventually "get it", I am posting.  Glad you took the time to convert those projects, but you really haven't addressed the problem of code bloat?  Taking selected projects from another web site isn't exactly validation that Microsoft doesn't have a code bloat problem.

    Bad programming exists everywhere, some done simply because of time constraints, some done because it works, some done to retain a level of compatibility, some just bad programming ... either way, not really my place to judge and I'm not sure why another developer would judge?  And again this doesn't have anything to do with code bloat -- it is still code bloat?

    I have elected to NOT use MVVM and although some do, it's CLEARLY a minority (simple forum thread count can confirm it's relatively small adoption rate).  I don't have any issue with you liking it or others liking it, but the problem with "soup of the day" methodology/implementations is that other more flexible solutions that don't promote code bloat are never addressed by Microsoft.

    I've provided plenty of feedback over the years, but thanks for the link anyway.  My feedback however would require Microsoft to consolidate projects and we all know that interdepartmental rivalry/conflicts for power/resources within Microsoft is fairly rampant (many former execs have publically exposed this corporate problem at Microsoft) -- and this sadly is detracting from clear unified direction.  What we end up with is all these "soup of the day" releases rather than a single clear direction of which can evolve over time rather than be old discarded and unsupported technology in less than a year or two ... where is re-usability?

    Before you say "oh but this is different" ... think about it, is it really?

    Rob

     

    Wednesday, September 07, 2011 4:12 PM
  • Taking selected projects from another web site isn't exactly validation that Microsoft doesn't have a code bloat problem.

    Hmm, take c++ project. Port it to .NET. .NET code SIGNIFICANTLY smaller. If that is a typical result, then you can hardly say that Microsoft has a bloat problem. And if they do, everyone else has it SIGNIFICANTLY worse.

    I have elected to NOT use MVVM and although some do, it's CLEARLY a minority

    It's easy to separate those who have from those who haven't. Senior skilled developers do it, junior developers don't. And before anyone takes offense, spare me.

    is that other more flexible solutions that don't promote code bloat are never addressed by Microsoft.

    What are these magical solutions of which you speak? .NET solutions are easily 5x more elegant than ANYTHING ever developed by humans. For example, does any other general purpose programming language have LINQ?

    What we end up with is all these "soup of the day" releases rather than a single clear direction

    I'm curious what standard you are holding Microsoft to. Obviously they could be better, and there have certainly been hints that Windows 8 will take a big step towards the consolidation you are looking for. That said, is Apple any better? Or Oracle? I can write managed code for Windows, Phone, XBOX, MAC, and even Linux. Yes, Java (a horrific language) can approach this, but hardly in a sane or consistent fashion.

    where is re-usability?

    I have .NET code from eight years ago that still runs just fine. I could have it running on my phone in no time at all. And on my XBOX. And on a MAC via Silverlight. It's one of the reasons so many of us were pissed by all the C++/JS/HTML bullshit that Microsoft floated a couple months ago. I really do wonder what significant technology Microsoft has "discarded" after "a year or two."

     

     

     

     

    Wednesday, September 07, 2011 4:58 PM
  • 1.  How is that cost effective for a company ($11,800 per head in MSDN license and about 100K - 200K per developer)?

    What does the cost of the Visual Studio Ultimate version of MSDN have to do with MVVM? MVVM works fine with Visual Studio Express.

    Developers are not adopting Microsoft tools in mass because Microsoft keeps re-inventing the same wheel over and over rather than sticking with one wheel and evolving it -- why can't Microsoft produce an evolution of a product?

    What does this have to do with MVVM? MVVM wasn't invented by Microsoft, it is an existing pattern that was named by John Grossman (MVVM) and Martin Fowler (MVP). If you are talking about all of the frameworks that have grown up around MVVM (like MVVM Light, Calibre, etc) you will notice that except for Prism none of them were made by Microsoft. They were made by the community. MVVM has always been a community driven concept.

    Wednesday, September 07, 2011 5:12 PM
  • Depends on the C++ project and whether it will be smaller and use of MSVC.  .NET framework install is huge.

    SL4 install is not too large (for an Add-In) but try to locate .SqlClient in the SL libraries ;)  -- guess it's time to write a ton of web services and wrapper classes.

    Senior and Junior developers -- what's that go to do with anything?

    Never spoke of a Magical solution, again that's not a justification for "soup of day" nor code bloat.  It's what could have been rather than the mess we currently have because of corporate/departmental rivalry.

    Apple/ADC certainly is cheaper and they do a better job of 32/64bit integration -- it's not perfect either, but they do stayed more focused on a steady technology path and don't have "soup of day" introduced every year.  But again, not really relevant, this is about what Microsoft isn't doing.

    Ah, managed code ... I recall a recent survey regarding .NET managed assembly usage ... it was something like 33% of .NET framework is actually used by 97% of the applications tested (that were used in the survey) ... yet the end user gets 67% of the framework like it or not.  Why can't a .NET framework application just require the components it uses rather than the entire framework?  This would make for smaller downloads and quicker installs and faster startups on the client.  Why hasn't Microsoft done this?  Too busy coming up with "soup of day" new technologies?  In fact, your example of "I have .NET code from 8 years ago that still runs fine today" helps prove my point.

    Rob

     

    Wednesday, September 07, 2011 5:28 PM
  • What does the cost of the Visual Studio Ultimate version of MSDN have to do with MVVM? MVVM works fine with Visual Studio Express.

    Large projects will most likely have Team Foundation setup for source code control and documentation and bug tracking etc.  Team Foundation is in Ultimate version only ... along with other key elements that large scale projects typically benefit from.

    What does this have to do with MVVM? MVVM wasn't invented by Microsoft, it is an existing pattern that was named by John Grossman (MVVM) and Martin Fowler (MVP). If you are talking about all of the frameworks that have grown up around MVVM (like MVVM Light, Calibre, etc) you will notice that except for Prism none of them were made by Microsoft. They were made by the community. MVVM has always been a community driven concept.

    MVVM is part of the VS 2010 environment templates and was originated by Microsoft (Martin Fowler) and based on MVC/MVP.  Yes it is a architectural pattern that promotes more code bloat in the name of further separation of UI from business logic from back end. 

     

    Wednesday, September 07, 2011 5:38 PM
  • Depends on the C++ project

    Not really. The .NET framework simply has got too much stuff in it.

    .NET framework install is huge.

    Who cares.

    SL4 install is not too large (for an Add-In) but try to locate .SqlClient in the SL libraries

    Seriously? My car doesn't have booster rockets to get it into orbit either. Why would a client technology meant to run in a sandbox have database access libraries?

    Senior and Junior developers -- what's that go to do with anything?

    I think you're proving my point.

      It's what could have been rather than the mess we currently have because of corporate/departmental rivalry.

    So your gripe is that Microsoft hasn't lived up to a standard that no human software organization ever has? And really, that "mess" lets me move from desktop, to phone, to game machine, to browser, etc etc fairly easily.

    Apple/ADC certainly is cheaper and they do a better job of 32/64bit integration

    Ahahahahahahahahahhahahah. Wait wait. Ahahahahahahahhhahahah. Cheaper? Aahahahahhahahaha. http://developer.apple.com/programs/start/standard/ See the dollar signs at the end? Can you even get the SDK without dropping cash? As for 32/64 bit, my pure .NET apps are both, and I didn't even need to think about it.

    yet the end user gets 67% of the framework like it or not.

    Who effing cares? Is it even 100MB? They got 66MB of extra stuff? The client profile is even smaller. 2 Terrabyte drives selling for $120 and you're complaining about <50MB of disk space???

    Why can't a .NET framework application just require the components it uses rather than the entire framework?

    You seriously don't know the answer to this question?

    Too busy coming up with "soup of day" new technologies?

    No, just tackling real problems. Desktop disk utilization isn't one of them these days.

      In fact, your example of "I have .NET code from 8 years ago that still runs fine today" helps prove my point.

    You're proving a point alright, just probably not the one you think. You talk about Microsoft abandoning technologies after a year, and I mention eight year old code that I can easily compile for PC, web, phone, and game console. So now the fact that the code still compiles and runs is somehow a bad thing? Wow.

    Wednesday, September 07, 2011 6:16 PM
  • An interesting thread, the initial posts raised some drawbacks with MVVM that I feel to an extent are valid but I do feel most of the points are overly critical and are more a result of lack of experience/understanding using the pattern.

    Our company have developed a fairly large financial LOB application which granted consists predominantly of CRUD forms which MVVM nails on the head. But we also have plenty of more complex GUI stuff such as drag and drop, dockable panels (dashboards), pivot viewer, charting etc. Nothing special I admit but people have been using these as examples of where MVVM falls over and is a difficult pattern to work with. I would agree this sort of functionality has no place in the ViewModel but I would equally argue it doesn't necessarily have a place in the code behind either. We have achieved all the aforementioned functionality using behaviours and custom controls which we can then use declaratively in XAML plus it's all reusable, our whole app probably has only a handful of code lines in code behind files. The point about binding bools to visibility properties again at first I admit feels funny but when you decide actually I want to bind that bool to an enabled property or have it change a colour instead, then you see the value or having a decoupled ViewModel. Also in reality a small collection of converters will end up covering about 90% of your use cases our devs don't even think about it anymore. Every so often we do have to put something in code behind and developers shouldn't be afraid of that but MVVM is an excellent pattern for medium to large enterprise applications. Our app is simpler, more testable and has a smaller codebase as a result of it. We are also starting to use it in our HTML5 mobile apps too using KnockoutJS much neater JS!  All that said MVVM is not a good fit for every app and I readily accept that it what the devs feel is a good fit for them but give it a fair look.

    Wednesday, September 07, 2011 6:17 PM
  • All that said MVVM is not a good fit for every app and I readily accept that it what the devs feel is a good fit for them but give it a fair look.

    Agreed. I think the real problem is when people who don't really understand the pattern get religious about "the code behind must be empty." Then when others try and follow that misconception the real frustration starts. Finally, there is the over reaction that leads to throwing the baby out with the bath water and "venting threads."

    Wednesday, September 07, 2011 7:23 PM
  • Oh Jack, shaking head now ... not sure where to start with your assertations ... trying running OLEDB in 64bit ... oh wait you probably "don't care". 

    Well my end users/clients don't like waiting for a long long downloads (many of them are remote locations) and install process of .NET framework ... but again I'm sure you "don't care".

    And those real problems are only relevant to you because, let me guess ... you "don't care".

    I can compile and run games and applications I produce 25 years ago ... so, that's not the point so you have missed the point entirely.

    You apparently know very little about ADC, yes it can be obtained for free and their top tier membership is considerably less expensive than $11,800 as per MSDN Ultimate.

    Anyway, you seem to be getting really emotional about this, so I'll check out of this thread.

     

    Wednesday, September 07, 2011 7:24 PM
  • trying running OLEDB in 64bit ... oh wait you probably "don't care". 

    OLEDB??? Um, yah. Don't care at all. Are you also upset that Commodore 64 games don't run 64 bit?

    Well my end users/clients don't like waiting for a long long downloads (many of them are remote locations) and install process of .NET framework ... but again I'm sure you "don't care".

    A one time install every two or three years. You guessed it, who cares? And seriously, do your users have 28.8 modems? So you expect Microsoft to cater to your edge cases? Netflix is streaming petabytes of movies, and you're stressing about an install that is the equivalent of a tiny youtube video?

    I can compile and run games and applications I produce 25 years ago ... so, that's not the point so you have missed the point entirely.

    Uh huh. You can break out a project from 25 years ago and run it FLAWLESSLY on your PC, phone, and web browser? Your PC has native support for SoundBlaster drivers and Windows 7 will let your game talk directly to the hardware? You're not even making sense. I can take my eight year old .NET code and about the only clue that you would have that it wasn't written last week was that it wouldn't be littered with LINQ and generic collections. That's stability and reusability if you ask me.

    You apparently know very little about ADC

    Got me there, but I know Apple, and they are never cheap. I haven't had an MSDN membership for a few years now, and I haven't really missed it. I can download free versions of Visual Studio and SQL. Your repeated harping about the $11,800 cost for MSDN Ultimate seem pretty silly considering you don't even need any MSDN license at all to do development.

    Anyway, you seem to be getting really emotional about this

    Emotional? I'm laughing that your main rants against MVVM appear to be that

    1) MSDN is expensive

    2) The .NET framework at < 50MB takes up a lot of diskspace and bandwidth

    3) Microsoft discontinued OLEDB

    Wednesday, September 07, 2011 7:59 PM
  • When I wrote a response to this thread back in June I was still very new to MVVM, scratching my head trying to figure out why anyone would want to use it.  I’ve since taken a role with a large financial company that uses WPF/SL extensively.  I’m writing a very complex app in WPF using MVVM.  I don’t have a choice – MVVM is the company standard.   I can now tell you from firsthand experience that MVVM has added enormous complexity to this application with minimal tangible benefit.  It’s not worth it – no way no how.  Not even close.

    For the record I will agree that the objectives of MVVM are worthy however the tooling/framework has not evolved to the point where there is a positive ROI.

    Speaking of tooling, a big problem with MVVM is that it completely omits the idea of a  presentation layer.  Anyone who has written a LOB application larger than MyTaskManger knows you need a presentation layer.  This weak workaround is inefficient and lacking.   This is why all the examples of RIA Services and Entity Framework only show how to work with entities that match the data store.  How often do you do that in real life? Rarely! 
    What we really need is a way to implement a presentation layer (ideally as part of entity framework).  A better acronym is PMVVM i.e. Presentation Model, View, View Model.  ORM's pretty much automate your DAL so why not just factor that out.


    http://davybrion.com/blog/2010/07/the-mvvm-pattern-is-highly-overrated/

    A good read:
    http://neverindoubtnet.blogspot.com/2011/05/mvvm-backlash.html


     

    Wednesday, September 07, 2011 9:26 PM
  • Speaking of tooling, a big problem with MVVM is that it completely omits the idea of a  presentation layer.  Anyone who has written a LOB application larger than MyTaskManger knows you need a presentation layer.  This weak workaround is inefficient and lacking.   This is why all the examples of RIA Services and Entity Framework only show how to work with entities that match the data store.  How often do you do that in real life? Rarely! 

    I think what RIA Services is calling presentation model isn't really a presentation model.

    Lets get the whole current MVVM (w/ RIA Services) stack layed out here:

    View <> ViewModel <> DataService <> DomainContext <> DomainService <> DAL <> Database

    That can be further broken up to be

    Presentation (View <> ViewModel)
    BLL layer (DataService <> DomainContext <> DomainService)
    Data Layer (DAL <> Database)

    At the DAL level, the traditional EDMX flavor of Entity Framework is giving way to the code first flavor of Entity Framework. Personally, I have switched over 100% to using POCOs (although I do design the database first). Some people also put a repository between the DAL and the DomainService. I think much of your problem with Entities being 1:1 with the database will be fixed over time as we stop using EDMX files that are just generated from the database.

    The DomainService gets populated using scaffolding and the DomainContext is generated automatically at compile time based on the DomainService.

    I have looked into scaffolding out the DataService but I am not sure how useful that would be.

    So, presentation model. I am unsure of where exactly a Presentation model Layer should fit. Would the ViewModel use the presentation layer to wrap an Entity before exposing it to the View? Or, should the Data Service do the wrapping before it gets to the ViewModel? The point being, since the DomainService/DomainClient represent the business logic layer of the application putting a presention layer behind the DomainService doesn't make any sense to me.

    I usually agree with Ward and I do think MVVM has been way oversold. It is just a pattern, and it can be a really simple pattern at that. Personally, I follow the pattern because I find it makes development much faster for me. In my experience, where people get stuck is trying to use the drag and drop style of development which in real life just doesn't work. MVVM is a relatively easy to use, proven pattern that I can point people at. More importantly, when someone is having a problem it is easier to help them when we have shared patterns that we can all refer to. Honestly, if someone wants to put all of their code into their code behind I don't really care but it does make it a lot harder to help people debug their problems when they need help.

    http://davybrion.com/blog/2010/07/the-mvvm-pattern-is-highly-overrated/

    I am sorry, but that article is funny. Considering that the MVVM pattern IS the MVP pattern, doing a series of blog articles trying to prove that MVP is better than MVVM is a pretty pointless thing to attempt. In effect, all he did was create yet another MVVM implementation.

    Thursday, September 08, 2011 12:14 AM
  • OLEDB??? Um, yah. Don't care at all.

    Well Jack, I wish I could go to my clients and end users and dictate that they must dump all their MS Access 64bit software (Office 2010 64bit), but I can't because these are the people that provide my company money to get a job done.  I don't have the luxury to dictate terms to my clients and end users.  My end users are rarely computer savy, many are iPad and/or Apple based but not all (about a 60/40 mix).

    I can understand that you like MVVM, it obviously seems to be a solution for you and that's great.  It would appear to me that you are in a position to dictate what your end users will have or must have ... that's not my situation.  Clearly my world of end users/clients is very different from yours ... I don't have the luxury of say "I don't care".

    My users have a mix of different technologies from very unreliable satalitte service to you guessed it modems (in the more extreme situations) but some also have very high speed fiber.  But again, it's not my position to dictate what they must have in terms of hardware and software.  My client are also multi-platform and again, not something I can dictate to them.

    I have looked into MVVM and came to the same conclusions as swheat, the ROI just isn't there and for my company that's the bottom line.  Then there is WPF which is sorta the parent of SL XAML but yet not really (because of multi-platform) ... then there is WCF, WCF RIA, WCF SL enabled, and ASMX and ... all do about the same with slight variations.

    As nice as it is to have "elegance" in coding solutions, "elegance" is rarely easily maintainable by various developers of different levels of experience .. and that's a BIG consideration for anyone looking at the long term projects with planned upgrade cycles.

    But the real point I want to make here is NOT do away with MVVM, but get Microsoft to stop developing for Corporate environments almost exclusively.  The reason I went with SL was for multi-platform support because that's the reality of my world, Microsoft is NOT the dominant player and has NO leverage ... and I'll think you'll find that becoming more and more common.

    What's coming out of Redmond for development tools, platforms, and solutions is almost certainly a result of Microsoft trying to hold onto their OS platform and Browser leverage.  Times are changing, this is no longer the case IE dominance nor OS dominance and the tools I need just currently don't exist ... SL4 is the closest, SL5 will be even better when it has Full Trust support as I need to be able to access local files across platforms with no directory restrictions.  And again, OS platform is NOT something I can dictate.  SL appears to moving in the right direction ... I hope it's not abandon before they permit Synchronous web service calls like every other platform does except SL (even .NET framework allows that) ... and no I don't want to start a debate on locking the UI thread.

    Maybe Microsoft has just decided to consolidate their products to the corporate world ... who knows, they could have just tossed in the towel and this is how Microsoft want there future to be.  I don't know, but I think it's a short sighted if that really is the objective.

    Rob

    Thursday, September 08, 2011 2:06 AM
  • @ColinBlair:

    Whoops my bad – I said presentation layer I meant presentation model.  Colin I think you got that but I need to clear it up.

    I’m not going to try to figure out the mechanics of how a presentation model should be implemented.  It should be the viewmodels view of the data and hopefully a tool like EF can take care of the busy work of mapping the data.  It looks like you are on your way to sorting it out don’t let me stop you.

    I will comment again on the importance of presentation model however because it seems the concept has been almost completely ignored.  I can hardly think of a view I’ve created that does not require me to de-normalize my data somehow in order to present it. Writing presentation classes by hand pretty much negates the goodness EF provides in terms of keeping managed code in sync with the database.  There are also design considerations on how/when/what data to shuttle back and forth between the client and server.  My point is that the presentation model is as important as the view or the model in terms of when, where, and how it is used.  A presentation model is not just for large or complex apps. 

    I find it makes development much faster for me. In my experience, where people get stuck is trying to use the drag and drop style of development which in real life just doesn't work.


    LOL come on Colin you are talking to people who do this for a living!  This has nothing to do with drag and drop. 

    Honestly, if someone wants to put all of their code into their code behind I don't really care but it does make it a lot harder to help people debug their problems when they need help.

    Really?  I’ve found the exact opposite to be true.  Why don’t you write a class that has a hyperlink button named Save that calls a method of the same name.  Show logic to display a variable error  message to the user in a fictitious circumstance.  Show logic to prompt the user to overwrite existing data if it (fictitiously) exists.  Show logic to display a confirmation upon completion of the method.
    Lets see the code to do that using MVVM vs.  code behind.

     

     


     

    Thursday, September 08, 2011 12:27 PM
  • Why don’t you write a class that has a hyperlink button named Save that calls a method of the same name.

    I'm not sure how that's even relevant in a MVVM discussion. That sounds more like bad coding practices.

    Show logic to display a variable error  message to the user in a fictitious circumstance.

    The ViewModel raises an event InternalError. The view handles it and shows the error text. The unit test either ignores it or fails the test given the circumstances. If all the logic is in your code behind, how does a unit test complete when waiting for user input?

    Show logic to prompt the user to overwrite existing data if it (fictitiously) exists. 

    If the business rules require a confirmation, again, raise an event or do a callback.

    Show logic to display a confirmation upon completion of the method.

    Same as above. Yes, the MVVM approach may require a bit more code, but it's a lot easier to test.

     

     

    Thursday, September 08, 2011 1:12 PM
  • I'm not sure how that's even relevant in a MVVM discussion. That sounds more like bad coding practices.

    You sound like a bright guy if you'd stop beating your chest people might take you seriously.

     

     

    Thursday, September 08, 2011 1:20 PM
  • I can hardly think of a view I’ve created that does not require me to de-normalize my data somehow in order to present it.

    Bingo!!  In the real world of end users they do NOT think in terms of normalized data, only us developers do.  And you CAN NOT force them to think that way ... right or wrong.

    I still have not seen how MVVM is better for testing?  It hasn't improved coverage/accuracy nor reduced testing time from what we've done - again back to ROI.  The most difficult testing is usually around web services once they are deployed from a development PC to a Test Server.

    Thursday, September 08, 2011 1:34 PM
  • I'm not sure how that's even relevant in a MVVM discussion. That sounds more like bad coding practices.

    I'm beating my chest by saying that giving a variable and a method the same name is bad programming? Shrug. There have been some pretty bizarre vents against MVVM. Obviously people can code any way they want, but MSDN being expensive or the size of the .NET framework aren't legit criticisms of MVVM.

    Thursday, September 08, 2011 2:01 PM
  • No, you are beating your chest by responding to valid arguments with trival non-sequiturs.  Nobody is fooled.  If you can't make a valid point STFU and get out of here.

     

    Thursday, September 08, 2011 2:18 PM
  • Obviously people can code any way they want, but MSDN being expensive or the size of the .NET framework aren't legit criticisms of MVVM.

    Agree, and I am perhaps guilty of some sidetracking ... but my primary point was I'd like to see something other than MVVM, something more unified and less restrictive.

    I'm getting a little exhausted of Microsoft trying to dictate how we should present a UI, how we should communicate with a database, and how we should generate a ton of excessive code to do it "their way" because Microsoft knows best.  I just want Microsoft to stop making assumptions and stop trying to leverage their way of life ... Microsoft have NOT and could NEVER possibly know all the variance in environments and situations in which developers must find solutions.

    I know Microsoft, the next VS version and we'll all have to follow MVVM like it or not.  Same restriction got placed on SL web service calls that MUST all be Async because Microsoft have deemed that the UI should never be locked and there is no situation where that is justified -- how could Microsoft possible know every situation ... it's a big assumption, one that is WRONG. 

    I'm sure Windows Forms applications are the next target, they'll become XAML also -- which BTW is a much slower read/parse than how Windows Forms is currently stored to file and read from file.  But because Microsoft believe that ALL DEVELOPMENT projects should have separation of UI developer from Middle tier from Back end ... which in my world is NEVER the case ... all they've accomplished is code bloat, and new things to learn (as far as XAML and WPF that's a lot to digest), and still have not reduced ROI.

    All I've seen out of Microsoft so far is the piling up of more things to learn with little or no benefit in terms or ROI.

    Like I've been trying to say, Microsoft NEED to consolidate all these technologies and implementations and stop making assumptions about environments they could never possibly predict and please stop the unwanted restrictions.

    And yes some of this is not directly relevant to MVVM, but some of it is.

    Rob

    Thursday, September 08, 2011 2:51 PM
  • but my primary point was I'd like to see something other than MVVM, something more unified and less restrictive.

    Fair enough, but MVVM wasn't really the brainchild of Microsoft. The binding and command system provided by WPF was just really conducive to its evolution.

    I'm getting a little exhausted of Microsoft trying to dictate how we should present a UI, how we should communicate with a database

    I think these things just kind evolve as the industry changes and Microsoft attempts to provide better solutions. Take languages for example, Java is pretty much a stone age language at this point because there's been no driving force behind it. In contrast C# has matured beautifully with features like LINQ. Yes, we had to learn something new, but wow, what a payoff.

    Same restriction got placed on SL web service calls that MUST all be Async because Microsoft have deemed that the UI should never be locked and there is no situation where that is justified

    Believe me, I was quite vocal in my advocacy for synchronous calls. There were technical factors that significantly influenced their decision on that one. It had nothing to do with locking the UI thread because nothing can stop a malicious coder from running while {true;} on the UI thread. The Netscape plugin API didn't support synchronous calls, so Microsoft could either follow the API or rely on the browser's XMLHTTP implementation (and this introduced all sorts of other issues.) If Microsoft wanted to protect the UI thread, all they would have done was check if the call was on the UI thread and raise an exception (they can call CheckAccess too.)

    I'm sure Windows Forms applications are the next target

    Uh, Winforms isn't getting updated, it's already dead.

    which BTW is a much slower read/parse than how Windows Forms is currently stored to file and read from file.

    Not surprising since it's doing a whole lot more.

    But because Microsoft believe that ALL DEVELOPMENT projects should have separation of UI developer from Middle tier from Back end ... which in my world is NEVER the case

    They learned from Winforms and came up with a declarative approach. If you don't need the separation, don't use it, but there's a whole lot more going on in WPF than separation of concerns. Animation, overlays, binding, routed events, etc, etc.

    all they've accomplished is code bloat

    On the contrary, if you wanted to build a Winform app that looked the same as a WPF app, you'll end up with a lot more procedural code.

    and new things to learn

    No argument there, but that's just the nature of this business. If I didn't get any benefit from having to learn all this new stuff, yah, I'd be pissed. That's not the case though with WPF, stuff that would have taken hours in Winforms can be done in minutes. For example, how easily could you show a datagrid in a tooltip in Winforms?

    more things to learn with little or no benefit in terms or ROI.

    Guess your mileage varies significanly from mine.

    Thursday, September 08, 2011 3:22 PM
  • If you can't make a valid point STFU and get out of here.

    STFU? What are you five? You stated...

    Show logic to display a variable error  message to the user in a fictitious circumstance.  Show logic to prompt the user to overwrite existing data if it (fictitiously) exists.  Show logic to display a confirmation upon completion of the method.

    I responded with how easy it was to do in MVVM and that the resulting code was easy to unit test. You didn't respond to that at all, but apparently took offense to my saying that naming a global variable and a method the same was bad coding. If you're doing that on a routine basis, should I really be giving your insights on MVVM significant weight?

     

    Thursday, September 08, 2011 3:31 PM
  • MVVM wasn't really the brainchild of Microsoft

    Yes and No, but regardless Microsoft adopted it.

    I think these things just kind evolve as the industry changes and Microsoft attempts to provide better solutions

    Microsoft drove much of the direction while some was in response to existing conditions, but don't kid yourself a lot of that drive was about staying with Microsoft platforms.

    In contrast C# has matured beautifully with features like LINQ.

    LINQ is actually a better syntactical fit with VB not C#, but yes it's kinda nice -- but really somewhat redundant, but it's not "required" thank goodness.

    Uh, Winforms isn't getting updated, it's already dead.

    Click Once is almost dead, which is probably what would have saved WinForms in terms of deployment.  But without .NET Framework being available on other platforms (MonoProject is pretty much dead) it's a dead end technology that Microsoft have NO plans to "evolve" to OSX or any other platform (as they had originally promised they would do).  But again all kinds of restrictions were placed around Click Once so that only relatively simple applications could benefit.

    For example, how easily could you show a datagrid in a tooltip in Winforms?

    But what we can do today in WPF and SL was long ago available in WinForms via numerous 3rd party tools/controls (worse case write your own).  Going back 10+ years, I recall a Resize control that handle ALL aspects of form/window sizing an ensured a nice UI when one sized a window ... it was a (cheap) control that I rarely had to think about ... that was a big ROI.  Not to mention if you really wanted to get involved in DX, you could ... again this was 10 years ago.  But most of what you see in WPF today was available long ago for WinForms, but rather than evolve WinForms, Microsoft just abandoned it.

    but that's just the nature of this business.

    I disagree, Microsoft could have elected to move in a direction that evolved their products rather "start all over from scratch" as they did.

    If you don't need the separation, don't use it

    I would love NOT to use it, but what are my options?  If I want central deployment, unresticted access to local client resources, and ability to work cross platforms, then SL is my only choice and it requires separation of UI ... which really isn't separation because the same developer does both which isn't good for ROI.

    But to put this in real world perspective, I've been trying to hire a SL UI / Graphics Designer ... my only requirement is they are proficient with Blend 4 and have some VS 2010 knowledge (but not much) and have some artistic ability and can use Photoshop and/or Illustrator.   Guess how many people I've found that fit this job skill set ... drum roll ... NONE!  So if UI separation is the goal that break teams up, there certainly doesn't appear to be any real job market here.  The applicants I've review/interviewed (I got a ton of them in a bad economy, so many I had to filter out the not even close applicants) are not skilled for UI/Graphics Design only ... they are either too artistic and can't navigate around Blend 4 or they are straight up coders that know enough of each but don't excel in UI/Graphics.  So UI separation may fill some conceptual methodology to programming an application, but appears to be more mythical in real world resource availability.

    So the obvious question is ... what's really driving this?  To me it's a process without a purpose and I have very little options to NOT follow the process which will NOT be good for ROI. Sooo...I'm back at square one ... Microsoft are on a course that is pretty much excluding me from using their solutions because my world doesn't fit their container/concepts.

    Rob

     

     

     

    Thursday, September 08, 2011 4:22 PM
  • Really?  I’ve found the exact opposite to be true.  Why don’t you write a class that has a hyperlink button named Save that calls a method of the same name.  Show logic to display a variable error  message to the user in a fictitious circumstance.  Show logic to prompt the user to overwrite existing data if it (fictitiously) exists.  Show logic to display a confirmation upon completion of the method.
    Lets see the code to do that using MVVM vs.  code behind.

    This is a lot rougher then I would like. In a real application the local view wouldn't need to register the message handling (that would be up at my shell level) and I don't like how the child window doesn't close before the message boxes show up but in a real app there would be server calls in the middle that would give the window time to hide itself.

    http://bit.ly/o1mDov

    Thursday, September 08, 2011 5:02 PM
  • Set visibility before closing to avoid animation delay issue -- unless of course you like the closing animation on a ChildWindow.

    I don't like the way setting a DialogResult = True will actually close the ChildWindow -- not consistant with other MS technologies.

    Rob

    Thursday, September 08, 2011 5:47 PM
  • Set visibility before closing to avoid animation delay issue -- unless of course you like the closing animation on a ChildWindow.

    Good tip

    I don't like the way setting a DialogResult = True will actually close the ChildWindow -- not consistant with other MS technologies.

    That is also how DialogResult works in Windows Forms. Not saying I like it either, but it is consistent.

    Thursday, September 08, 2011 6:25 PM
  • Colin you are a great sport for doing this.  If your app isn't the poster child for the "MVVM-will-make-you-comatose" camp than nothing else is!  That isn't a slam against you personally - quite the contrary in fact.  You did a great job using a pattern that sacrifices simplicy for testability and the trade off is nowhere near fair as evidenced by your own code and comments. I have not actually run your code but be assured I will this evening. 

    This kind of logic should not even require a nanowatt of brain power. Look, the code below is all you need if you do it the "old" way.  I've made a very simple challange but even so I think the code you wrote demonstrates how much more complex a very simple task becomes when you use MVVM. Imagine what it's like when you have many different confirmations and code paths....(it becomes a mess very quickly).

    public partial class MainWindow : Window
        {
            public MainWindow()
            {
                InitializeComponent();
            }
    
            
            private void Save(object sender, RoutedEventArgs e)
            {
                if (new Random().Next(0, 2) == 1)
                {
                    MessageBox.Show("An error occured.  " + DateTime.Now.ToShortDateString(), "", MessageBoxButton.OK);
                }
                else
                {
                    bool OKtoSave = false;
                    bool dataExists = true; // Some method to lookup data somewhere
    
                    if (dataExists)
                        OKtoSave = MessageBox.Show("Do you want to overwrite existing data?", "", MessageBoxButton.YesNo) == MessageBoxResult.Yes ? true : false;
                    else
                        OKtoSave = true;
    
                    if (OKtoSave)
                    { 
                        // Do it
                        MessageBox.Show("Your data was saved.");
                    }
                }
            }
        }
     
     
    <Window x:Class="MVVMTest.MainWindow"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            Title="MainWindow" Height="350" Width="525">
        <Grid>
            <Button>
                <Button.Content>
                    <Hyperlink ButtonBase.Click="Save">Save</Hyperlink>
                </Button.Content>
            </Button>
        </Grid>
    </Window>
     
    Thursday, September 08, 2011 6:34 PM
  • Wow, I completely overestimated the complexity of what you were asking for. New version at:http://bit.ly/p2HTcG

    Here is my version of the code you posted. I probably should have gone ahead and renamed Save to SaveCommand so that I could name the below Save but I forgot.

     

    public void SaveStuff()
            {
                 if (new Random().Next(0, 2) == 1)
                 {
                     Messenger.Default.Send(new NotificationMessage("An error occured.  " + DateTime.Now.ToShortDateString()));
                }
                else
                {
                    bool dataExists = true; // Some method to lookup data somewhere
    
                    if (dataExists)
                        Messenger.Default.Send(new DialogMessage("Do you want to overwrite existing data?", (result) =>
                            {
                                if (result == MessageBoxResult.OK)
                                {
                                    //Do it
                                    Messenger.Default.Send(new NotificationMessage("Your data was saved."));
                                }
                            }) {Caption="", Button=MessageBoxButton.OKCancel});
                }
            }
     
    Thursday, September 08, 2011 7:48 PM
  • Now try the same challenge given by swheat without using MVVM Light and see how much infrastructure needs to be built up to do something so "simple".

    I also noticed a little bit of "cheating" in MainPage.xaml.cs. I see a two lines of code behind in the constructor to register with the MVVM Light Messenger. Was that code meant to be there?

    Wednesday, September 14, 2011 5:14 AM
  • Now try the same challenge given by swheat without using MVVM Light and see how much infrastructure needs to be built up to do something so "simple".

    I am not exactly sure what that would prove. We can spend all year doing this challenge again and again with different restrictions. "OK Colin, you wrote the application without using Visual Studio, writing your own MessageBox class, and only using your left hand. Now lets see how simple it is if do it with your monitor turned off". When I write an application that uses the MVVM pattern I use MVVM Light and MEFedMVVM, I am not interested in creating YAML (Yet Another MVVM Library). If you want to complain that MVVM is too complex because it requires libraries of prewritten code to make it easier to accomplish, I will not argue with you. I will however continue to use those same libraries because they work.

    I also noticed a little bit of "cheating" in MainPage.xaml.cs. I see a two lines of code behind in the constructor to register with the MVVM Light Messenger. Was that code meant to be there?

    That isn't cheating, and yes the code is supposed to be there. If the object was to play "don't put any code in the code behind" then yes that would be cheating. The object here was to use MVVM correctly to accomplish the task and that was using MVVM correctly. The ViewModel says, "I have a message" and the View then decides how to display that message to the user. In this case the View is deciding to show it as a message box but the View could just as easily have shown the message as a ChildWindow or displayed the message in a text box of the View itself. The point of using MVVM correctly in this scenario is showing separation of concerns. The ViewModel says "I need something displayed to the user". The View dicates how it gets shown. If all I wanted to do was show a MessageBox from the ViewModel then I could have just done a MessageBox. Show from within the ViewModel itself. Now THAT would have been cheating.

    That being said, in a real application that I would write the message listeners would not have been in the code behind of that view. It would have been handled up at the Shell level and I would probably use MEF to inject a class into the Shell to encapsulate the message handling code. In this case, there is only one View class in the entire application so I just stuck the message handling in the code behind the way it is shown in the MVVM Light documentation.

    Wednesday, September 14, 2011 8:31 AM
  • I also noticed a little bit of "cheating" in MainPage.xaml.cs. I see a two lines of code behind in the constructor to register with the MVVM Light Messenger. Was that code meant to be there?

    A common misconception about MVVM is the idea is to have no code is the .xaml.cs file, but the idea is something like to have only interface logic in the two view files, and it doesn't matter if both have code. If you love XAML and declarative code rather than procedural code, you will love how its often possible to do everything UI-related in XAML without any procedural code, but the important thing is separation of concern.

    I use the constructor of the view to initialize the view model when I want the view model to do something interface related but that could have different implementation based on the view. For example, the business logic dictates that a view is closed when a job is finished processing, so the view model can call its "CloseView" delegate property that was set by the view. Close will be different depending on if the view is a window or a tab or something else.

    Wednesday, September 14, 2011 11:27 AM
  • Colin I dont think you were cheating and I think using MVVM light is fair except I would like to see an integrated MS technology.  I like to have one vendor to throw something at when stuff dosnt work.  I pay money to MS so I dont have to use stuff that some guy writes in his garage on weekends.  Not that MVVM light is bad, it's just another integration point I dont want to have to deal with.

    Is the simplified code you posted testable?  If not, what do you have to do to make it testable?  I think we must include any code i.e. attributes, etc. required for testing since the primary benefit of MVVM is a testable viewmodel

    I was trying to make a small test case that is simple to write and compare.  Your "simplified" example is a couple lines longer than mine (the entire solution, not just the posted code).  Remember, 1 line in the test case is "X 100" or "X 200" or more in a real life app. 

    Here is a real life app that is open in VS right now as I write this post.  If you are thinking "God that must have been a bear to write" you are correct.  I'm posting XAML too.  Look at all the trigger code.... it the good old days we just typed in  a name for a click handler and visual studio generated the signature.  VS even choked at compile time if the handler dosent exist.  In the new, improved,  world of MVVM we don't get that.  We didn't used to have to write a property for SelectedValue (Text, etc.) or ItemsSource.  So, number of lines of code is important but so is framework support, which isnt there (yet?). 

    The following was inflicted upon me by MVVM.  I'm posting a fraction of the XAML in the view...  read it and weep kids:

     private string _error_Message;
            public string Error_Message
            {
                get { return _error_Message; }
                set { _error_Message = value; OnPropertyChanged("Error_Message"); }
            }
    
            private DateTime? _rRPDate_SelectedDate;
            public DateTime? RRPDate_SelectedDate
            {
                get { return _rRPDate_SelectedDate; }
                set { _rRPDate_SelectedDate = value; OnPropertyChanged("RRPDate_SelectedDate"); }
            }
    
            private bool _availType_Inbox_IsChecked;
            public bool AvailType_Inbox_IsChecked
            {
                get { return _availType_Inbox_IsChecked; }
                set { _availType_Inbox_IsChecked = value; OnPropertyChanged("AvailType_Inbox_IsChecked"); }
            }
    
            private bool _availType_CF_IsChecked;
            public bool AvailType_CF_IsChecked
            {
                get { return _availType_CF_IsChecked; }
                set { _availType_CF_IsChecked = value; OnPropertyChanged("AvailType_CF_IsChecked"); }
            }
    
            private bool _product_Type_TBA_IsChecked;
            public bool Product_Type_TBA_IsChecked
            {
                get { return _product_Type_TBA_IsChecked; }
                set { _product_Type_TBA_IsChecked = value; OnPropertyChanged("Product_Type_TBA_IsChecked"); }
            }
    
            private bool _product_Type_Pool_IsChecked;
            public bool Product_Type_Pool_IsChecked
            {
                get { return _product_Type_Pool_IsChecked; }
                set { _product_Type_Pool_IsChecked = value; OnPropertyChanged("Product_Type_Pool_IsChecked"); }
            }
    
            private bool _product_Type_ACMO_IsChecked;
            public bool Product_Type_ACMO_IsChecked
            {
                get { return _product_Type_ACMO_IsChecked; }
                set { _product_Type_ACMO_IsChecked = value; OnPropertyChanged("Product_Type_ACMO_IsChecked"); }
            }
    
            private bool _product_Type_UST_IsChecked;
            public bool Product_Type_UST_IsChecked
            {
                get { return _product_Type_UST_IsChecked; }
                set { _product_Type_UST_IsChecked = value; OnPropertyChanged("Product_Type_UST_IsChecked"); }
            }
    
            private bool _product_Type_TBill_IsChecked;
            public bool Product_Type_TBill_IsChecked
            {
                get { return _product_Type_TBill_IsChecked; }
                set { _product_Type_TBill_IsChecked = value; OnPropertyChanged("Product_Type_TBill_IsChecked"); }
            }
    
            private bool _product_Type_TIPS_IsChecked;
            public bool Product_Type_TIPS_IsChecked
            {
                get { return _product_Type_TIPS_IsChecked; }
                set { _product_Type_TIPS_IsChecked = value; OnPropertyChanged("Product_Type_TIPS_IsChecked"); }
            }
    
            private bool _product_Type_AGY_IsChecked;
            public bool Product_Type_AGY_IsChecked
            {
                get { return _product_Type_AGY_IsChecked; }
                set { _product_Type_AGY_IsChecked = value; OnPropertyChanged("Product_Type_AGY_IsChecked"); }
            }
    
            private bool _product_Type_Corp_IsChecked;
            public bool Product_Type_Corp_IsChecked
            {
                get { return _product_Type_Corp_IsChecked; }
                set { _product_Type_Corp_IsChecked = value; OnPropertyChanged("Product_Type_Corp_IsChecked"); }
            }
    
            private bool _product_Type_Prvt_IsChecked;
            public bool Product_Type_Prvt_IsChecked
            {
                get { return _product_Type_Prvt_IsChecked; }
                set { _product_Type_Prvt_IsChecked = value; OnPropertyChanged("Product_Type_Prvt_IsChecked"); }
            }
    
            private bool _product_Type_Conv_IsChecked;
            public bool Product_Type_Conv_IsChecked
            {
                get { return _product_Type_Conv_IsChecked; }
                set { _product_Type_Conv_IsChecked = value; OnPropertyChanged("Product_Type_Conv_IsChecked"); }
            }
    
            private bool _product_Type_PFD_IsChecked;
            public bool Product_Type_PFD_IsChecked
            {
                get { return _product_Type_PFD_IsChecked; }
                set { _product_Type_PFD_IsChecked = value; OnPropertyChanged("Product_Type_PFD_IsChecked"); }
            }
    
            private bool _product_Type_Muni_IsChecked;
            public bool Product_Type_Muni_IsChecked
            {
                get { return _product_Type_Muni_IsChecked; }
                set { _product_Type_Muni_IsChecked = value; OnPropertyChanged("Product_Type_Muni_IsChecked"); }
            }
    
            private List<String> _collateralList_SelectedItems;
            public List<string> CollateralList_SelectedItems
            {
                get { return _collateralList_SelectedItems; }
                set { _collateralList_SelectedItems = value; OnPropertyChanged("CollateralList_SelectedItems"); }
            }
    
            public List<string> CollateralList_ItemsSource { get; set; }
    
            private List<Entities.MGR> _pMList_SelectedItems;
            public List<Entities.MGR> PMList_SelectedItems
            {
                get { return _pMList_SelectedItems; }
                set { _pMList_SelectedItems = value; OnPropertyChanged("PMList_SelectedItems"); }
            }
    
            public List<Entities.MGR> PMList_ItemsSource { get; set; }
    
            private string _posInd_SelectedValue;
            public string PosInd_SelectedValue
            {
                get { return _posInd_SelectedValue; }
                set { _posInd_SelectedValue = value; OnPropertyChanged("PosInd_SelectedValue"); }
            }
    
            public List<string> PosInd_ItemsSource { get; set; }
    
            private string _acct_Nos_Text;
            public string Acct_Nos_Text
            {
                get { return _acct_Nos_Text; }
                set { _acct_Nos_Text = value; OnPropertyChanged("Acct_Nos_Text"); }
            }
    
            private bool _acctLevel_Detail_IsChecked;
            public bool AcctLevel_Detail_IsChecked
            {
                get { return _acctLevel_Detail_IsChecked; }
                set { _acctLevel_Detail_IsChecked = value; OnPropertyChanged("AcctLevel_Detail_IsChecked"); }
            }
    
            private string _coupon_From_Text;
            public string Coupon_From_Text
            {
                get { return _coupon_From_Text; }
                set { _coupon_From_Text = value; OnPropertyChanged("Coupon_From_Text"); }
            }
    
            private string _coupon_To_Text;
            public string Coupon_To_Text
            {
                get { return _coupon_To_Text; }
                set { _coupon_To_Text = value; OnPropertyChanged("Coupon_To_Text"); }
            }
    
            private string _cUSIPS_Text;
            public string CUSIPS_Text
            {
                get { return _cUSIPS_Text; }
                set { _cUSIPS_Text = value; OnPropertyChanged("CUSIPS_Text"); }
            }
    
            private string _exCUSIPS_Text;
            public string ExCUSIPS_Text
            {
                get { return _exCUSIPS_Text; }
                set { _exCUSIPS_Text = value; OnPropertyChanged("ExCUSIPS_Text"); }
            }
    
            private string _brokerIDs_Text;
            public string BrokerIDs_Text
            {
                get { return _brokerIDs_Text; }
                set { _brokerIDs_Text = value; OnPropertyChanged("BrokerIDs_Text"); }
            }
    
            private string _reservedByCode_SelectedValue;
            public string ReservedByCode_SelectedValue
            {
                get { return _reservedByCode_SelectedValue; }
                set { _reservedByCode_SelectedValue = value; OnPropertyChanged("ReservedByCode_SelectedValue"); }
            }
            public List<string> Reserved_By_ItemsSource { get; set; }
    
            private bool _exclude_HOLD_IsChecked;
            public bool Exclude_HOLD_IsChecked
            {
                get { return _exclude_HOLD_IsChecked; }
                set { _exclude_HOLD_IsChecked = value; OnPropertyChanged("Exclude_HOLD_IsChecked"); }
            }
    
            private string _maturityDates_SelectedValue;
            public string MaturityDates_SelectedValue
            {
                get { return _maturityDates_SelectedValue; }
                set { _maturityDates_SelectedValue = value; OnPropertyChanged("MaturityDates_SelectedValue"); }
            }
            public List<string> MaturityDates_ItemsSource { get; set; }
    
            private string _oFace_From_Text;
            public string OFace_From_Text
            {
                get { return _oFace_From_Text; }
                set { _oFace_From_Text = value; OnPropertyChanged("OFace_From_Text"); }
            }
    
            private string _oFace_To_Text;
            public string OFace_To_Text
            {
                get { return _oFace_To_Text; }
                set { _oFace_To_Text = value; OnPropertyChanged("OFace_To_Text"); }
            }
    
            private string _cF_From_Text;
            public string CF_From_Text
            {
                get { return _cF_From_Text; }
                set { _cF_From_Text = value; OnPropertyChanged("CF_From_Text"); }
            }
    
            private string _cF_To_Text;
            public string CF_To_Text
            {
                get { return _cF_To_Text; }
                set { _cF_To_Text = value; OnPropertyChanged("CF_To_Text"); }
            }
    
            private string _settled_CF_From_Text;
            public string Settled_CF_From_Text
            {
                get { return _settled_CF_From_Text; }
                set { _settled_CF_From_Text = value; OnPropertyChanged("Settled_CF_From_Text"); }
            }
    
            private string _settled_CF_To_Text;
            public string Settled_CF_To_Text
            {
                get { return _settled_CF_To_Text; }
                set { _settled_CF_To_Text = value; OnPropertyChanged("Settled_CF_To_Text"); }
            }
    
            private string _description_Text;
            public string Description_Text
            {
                get { return _description_Text; }
                set { _description_Text = value; OnPropertyChanged("Description_Text"); }
            }
    
            private string _duration_From_Text;
            public string Duration_From_Text
            {
                get { return _duration_From_Text; }
                set { _duration_From_Text = value; OnPropertyChanged("Duration_From_Text"); }
            }
    
            private string _duration_To_Text;
            public string Duration_To_Text
            {
                get { return _duration_To_Text; }
                set { _duration_To_Text = value; OnPropertyChanged("Duration_To_Text"); }
            }
    
            private string _repo_SelectedValue;
            public string Repo_SelectedValue
            {
                get { return _repo_SelectedValue; }
                set { _repo_SelectedValue = value; OnPropertyChanged("Repo_SelectedValue"); }
            }
            public List<string> Repo_ItemsSource { get; set; }
    
            private string _invInd_SelectedValue;
            public string InvInd_SelectedValue
            {
                get { return _invInd_SelectedValue; }
                set { _invInd_SelectedValue = value; OnPropertyChanged("InvInd_SelectedValue"); }
            }
            public List<string> InvInd_ItemsSource { get; set; }
    
            private string _collateral_SelectedValue;
            public string Collateral_SelectedValue
            {
                get { return _collateral_SelectedValue; }
                set { _collateral_SelectedValue = value; OnPropertyChanged("Collateral_SelectedValue"); }
            }
            public List<string> Collateral_ItemsSource { get; set; }
    
            private string _couponType_SelectedValue;
            public string CouponType_SelectedValue
            {
                get { return _couponType_SelectedValue; }
                set { _couponType_SelectedValue = value; OnPropertyChanged("CouponType_SelectedValue"); }
            }
            public List<string> CouponType_ItemsSource { get; set; }
    
            private string _securityType_SelectedValue;
            public string SecurityType_SelectedValue
            {
                get { return _securityType_SelectedValue; }
                set { _securityType_SelectedValue = value; OnPropertyChanged("SecurityType_SelectedValue"); }
            }
            public List<string> SecurityType_ItemsSource { get; set; }
    
            private string _issuer_SelectedValue;
            public string Issuer_SelectedValue
            {
                get { return _issuer_SelectedValue; }
                set { _issuer_SelectedValue = value; OnPropertyChanged("Issuer_SelectedValue"); }
            }
            public List<string> Issuer_ItemsSource { get; set; }
    
            private int _userRating_From_SelectedValue;
            public int UserRating_From_SelectedValue
            {
                get { return _userRating_From_SelectedValue; }
                set { _userRating_From_SelectedValue = value; OnPropertyChanged("UserRating_From_SelectedValue"); }
            }
            public Dictionary<string, int> UserRating_From_ItemsSource { get; set; }
    
            private int _userRating_To_SelectedValue;
            public int UserRating_To_SelectedValue
            {
                get { return _userRating_To_SelectedValue; }
                set { _userRating_To_SelectedValue = value; OnPropertyChanged("UserRating_To_SelectedValue"); }
            }
            public Dictionary<string, int> UserRating_To_ItemsSource { get; set; }
    
            private int _sPRating_From_SelectedValue;
            public int SPRating_From_SelectedValue
            {
                get { return _sPRating_From_SelectedValue; }
                set { _sPRating_From_SelectedValue = value; OnPropertyChanged("SPRating_From_SelectedValue"); }
            }
            public Dictionary<string, int> SPRating_From_ItemsSource { get; set; }
    
            private int _sPRating_To_SelectedValue;
            public int SPRating_To_SelectedValue
            {
                get { return _sPRating_To_SelectedValue; }
                set { _sPRating_To_SelectedValue = value; OnPropertyChanged("SPRating_To_SelectedValue"); }
            }
            public Dictionary<string, int> SPRating_To_ItemsSource { get; set; }
    
            private int _moodyRating_From_SelectedValue;
            public int MoodyRating_From_SelectedValue
            {
                get { return _moodyRating_From_SelectedValue; }
                set { _moodyRating_From_SelectedValue = value; OnPropertyChanged("MoodyRating_From_SelectedValue"); }
            }
            public Dictionary<string, int> MoodyRating_From_ItemsSource { get; set; }
    
            private int _moodyRating_To_SelectedValue;
            public int MoodyRating_To_SelectedValue
            {
                get { return _moodyRating_To_SelectedValue; }
                set { _moodyRating_To_SelectedValue = value; OnPropertyChanged("MoodyRating_To_SelectedValue"); }
            }
            public Dictionary<string, int> MoodyRating_To_ItemsSource { get; set; }
    
            private int _fitchRating_From_SelectedValue;
            public int FitchRating_From_SelectedValue
            {
                get { return _fitchRating_From_SelectedValue; }
                set { _fitchRating_From_SelectedValue = value; OnPropertyChanged("FitchRating_From_SelectedValue"); }
            }
            public Dictionary<string, int> FitchRating_From_ItemsSource { get; set; }
    
            private int _fitchRating_To_SelectedValue;
            public int FitchRating_To_SelectedValue
            {
                get { return _fitchRating_To_SelectedValue; }
                set { _fitchRating_To_SelectedValue = value; OnPropertyChanged("FitchRating_To_SelectedValue"); }
            }
            public Dictionary<string, int> FitchRating_To_ItemsSource { get; set; }
    
            private string _deliveryType_SelectedValue;
            public string DeliveryType_SelectedValue
            {
                get { return _deliveryType_SelectedValue; }
                set { _deliveryType_SelectedValue = value; OnPropertyChanged("DeliveryType_SelectedValue"); }
            }
            public List<string> DeliveryType_ItemsSource { get; set; }
    
            private string _agencyDeriv_SelectedValue;
            public string AgencyDeriv_SelectedValue
            {
                get { return _agencyDeriv_SelectedValue; }
                set { _agencyDeriv_SelectedValue = value; OnPropertyChanged("AgencyDeriv_SelectedValue"); }
            }
            public List<string> AgencyDeriv_ItemsSource { get; set; }
    
            private string _wALA_From_Text;
            public string WALA_From_Text
            {
                get { return _wALA_From_Text; }
                set { _wALA_From_Text = value; OnPropertyChanged("WALA_From_Text"); }
            }
    
            private string _wALA_To_Text;
            public string WALA_To_Text
            {
                get { return _wALA_To_Text; }
                set { _wALA_To_Text = value; OnPropertyChanged("WALA_To_Text"); }
            }
    
            private string _cPR6m_From_Text;
            public string CPR6m_From_Text
            {
                get { return _cPR6m_From_Text; }
                set { _cPR6m_From_Text = value; OnPropertyChanged("CPR6m_From_Text"); }
            }
    
            private string _cPR6m_To_Text;
            public string CPR6m_To_Text
            {
                get { return _cPR6m_To_Text; }
                set { _cPR6m_To_Text = value; OnPropertyChanged("CPR6m_To_Text"); }
            }
    
            private string _fICO_From_Text;
            public string FICO_From_Text
            {
                get { return _fICO_From_Text; }
                set { _fICO_From_Text = value; OnPropertyChanged("FICO_From_Text"); }
            }
    
            private string _fICO_To_Text;
            public string FICO_To_Text
            {
                get { return _fICO_To_Text; }
                set { _fICO_To_Text = value; OnPropertyChanged("FICO_To_Text"); }
            }
    
            private string _wAC_From_Text;
            public string WAC_From_Text
            {
                get { return _wAC_From_Text; }
                set { _wAC_From_Text = value; OnPropertyChanged("WAC_From_Text"); }
            }
    
            private string _wAC_To_Text;
            public string WAC_To_Text
            {
                get { return _wAC_To_Text; }
                set { _wAC_To_Text = value; OnPropertyChanged("WAC_To_Text"); }
            }
    
            private string _cPR3m_From_Text;
            public string CPR3m_From_Text
            {
                get { return _cPR3m_From_Text; }
                set { _cPR3m_From_Text = value; OnPropertyChanged("CPR3m_From_Text"); }
            }
    
            private string _cPR3m_To_Text;
            public string CPR3m_To_Text
            {
                get { return _cPR3m_To_Text; }
                set { _cPR3m_To_Text = value; OnPropertyChanged("CPR3m_To_Text"); }
            }
    
            private string _maxAOLS_From_Text;
            public string MaxAOLS_From_Text
            {
                get { return _maxAOLS_From_Text; }
                set { _maxAOLS_From_Text = value; OnPropertyChanged("MaxAOLS_From_Text"); }
            }
    
            private string _maxAOLS_To_Text;
            public string MaxAOLS_To_Text
            {
                get { return _maxAOLS_To_Text; }
                set { _maxAOLS_To_Text = value; OnPropertyChanged("MaxAOLS_To_Text"); }
            }
    
            private string _wAM_From_Text;
            public string WAM_From_Text
            {
                get { return _wAM_From_Text; }
                set { _wAM_From_Text = value; OnPropertyChanged("WAM_From_Text"); }
            }
    
            private string _wAM_To_Text;
            public string WAM_To_Text
            {
                get { return _wAM_To_Text; }
                set { _wAM_To_Text = value; OnPropertyChanged("WAM_To_Text"); }
            }
    
            private string _cPR1m_From_Text;
            public string CPR1m_From_Text
            {
                get { return _cPR1m_From_Text; }
                set { _cPR1m_From_Text = value; OnPropertyChanged("CPR1m_From_Text"); }
            }
    
            private string _cPR1m_To_Text;
            public string CPR1m_To_Text
            {
                get { return _cPR1m_To_Text; }
                set { _cPR1m_To_Text = value; OnPropertyChanged("CPR1m_To_Text"); }
            }
    
            private string _avg_LTV_From_Text;
            public string Avg_LTV_From_Text
            {
                get { return _avg_LTV_From_Text; }
                set { _avg_LTV_From_Text = value; OnPropertyChanged("Avg_LTV_From_Text"); }
            }
    
            private string _avg_LTV_To_Text;
            public string Avg_LTV_To_Text
            {
                get { return _avg_LTV_To_Text; }
                set { _avg_LTV_To_Text = value; OnPropertyChanged("Avg_LTV_To_Text"); }
            }
    
            private string _bBGTicker_SelectedValue;
            public string BBGTicker_SelectedValue
            {
                get { return _bBGTicker_SelectedValue; }
                set { _bBGTicker_SelectedValue = value; OnPropertyChanged("BBGTicker_SelectedValue"); }
            }
            public List<string> BBGTicker_ItemsSource { get; set; }
    
            private string _geo1_Text;
            public string Geo1_Text
            {
                get { return _geo1_Text; }
                set { _geo1_Text = value; OnPropertyChanged("Geo1_Text"); }
            }
    
            private string _geo2_Text;
            public string Geo2_Text
            {
                get { return _geo2_Text; }
                set { _geo2_Text = value; OnPropertyChanged("Geo2_Text"); }
            }
    
            private string _geo3_Text;
            public string Geo3_Text
            {
                get { return _geo3_Text; }
                set { _geo3_Text = value; OnPropertyChanged("Geo3_Text"); }
            }
    
            private string _geo4_Text;
            public string Geo4_Text
            {
                get { return _geo4_Text; }
                set { _geo4_Text = value; OnPropertyChanged("Geo4_Text"); }
            }
    
            private string _trait_SelectedValue;
            public string Trait_SelectedValue
            {
                get { return _trait_SelectedValue; }
                set { _trait_SelectedValue = value; OnPropertyChanged("Trait_SelectedValue"); }
            }
    
            public List<string> Trait_ItemsSource { get; set; }
    
            private POSITION_FILTER _currentPositionFilter;
            public POSITION_FILTER CurrentPositionFilter
            {
                get { return _currentPositionFilter; }
                set { _currentPositionFilter = value; OnPropertyChanged("CurrentPositionFilter"); }
            }
    
            private Dictionary<int, String> _position_Filters_ItemsSource;
            public Dictionary<int, String> Position_Filters_ItemsSource
            {
                get { return _position_Filters_ItemsSource; }
                set { _position_Filters_ItemsSource = value; OnPropertyChanged("Position_Filters_ItemsSource"); }
            }
    
            private int _position_Filters_SelectedValue;
            public int Position_Filters_SelectedValue
            {
                get { return _position_Filters_SelectedValue; }
                set { _position_Filters_SelectedValue = value; OnPropertyChanged("Position_Filters_SelectedValue"); }
            }
     
    <Border Width="140" Margin="3,0,3,0" BorderBrush="Silver" BorderThickness="2" CornerRadius="6" Grid.Row="0" Grid.Column="0" Grid.RowSpan="8">
                            <StackPanel Orientation="Vertical">
                                <Button Content="Collateral..." x:Name="btnClasses" Width="120"></Button>
                                <ListBox x:Name="lbCollateral" Width="140" SelectionMode="Multiple" Height="130" 
                                         ItemsSource="{Binding CollateralList_ItemsSource}" 
                                         >
                                    <i:Interaction.Triggers>
                                        <i:EventTrigger EventName="SelectionChanged">
                                            <galaExtras:EventToCommand Command="{Binding CollateralListChangedCommand}" CommandParameter="{Binding SelectedItems, ElementName=lbCollateral}"></galaExtras:EventToCommand>
                                        </i:EventTrigger>
                                    </i:Interaction.Triggers>
                                </ListBox>
                            </StackPanel>
                        </Border>
    
                        <Border Width="140" Margin="3,0,3,0" BorderBrush="Silver" BorderThickness="2" CornerRadius="6" Grid.Row="0" Grid.Column="1" Grid.RowSpan="8">
                            <StackPanel Orientation="Vertical">
                                <Button Content="PMs..." x:Name="btnPMs" Width="120" ></Button>
                                <ListBox x:Name="lbPM" Width="140" SelectionMode="Multiple" Height="130" 
                                         ItemsSource="{Binding PMList_ItemsSource}" DisplayMemberPath="FullName" SelectedValuePath="MGR_NO" >
                                    <i:Interaction.Triggers>
                                        <i:EventTrigger EventName="SelectionChanged">
                                            <galaExtras:EventToCommand Command="{Binding PMListChangedCommand, Mode=OneWay}" CommandParameter="{Binding SelectedItems, ElementName=lbPM}"></galaExtras:EventToCommand>
                                        </i:EventTrigger>
                                    </i:Interaction.Triggers>
                                </ListBox>
                            </StackPanel>
                        </Border>
    
                        <localControls:FormElement LabelText="Pos Ind:"  Grid.Row="0" Grid.Column="2">
                            <ComboBox x:Name="cbPosInd" Width="100" 
                                      SelectedValue="{Binding PosInd_SelectedValue, Mode=TwoWay}" 
                                      ItemsSource="{Binding PosInd_ItemsSource}"
                                      >
                                <i:Interaction.Triggers>
                                    <i:EventTrigger EventName="SelectionChanged">
                                        <galaExtras:EventToCommand Command="{Binding SearchCriteriaChangedCommand, Mode=OneWay}"></galaExtras:EventToCommand>
                                    </i:EventTrigger>
                                </i:Interaction.Triggers>
                            </ComboBox>
                        </localControls:FormElement>
    
                        <localControls:FormElement LabelText="Acct No:" Grid.Row="0" Grid.Column="3">
                            <StackPanel Orientation="Horizontal">
                                <TextBox x:Name="txtAcctNo" Width="80" Text="{Binding Acct_Nos_Text, Mode=TwoWay}" >
                                    <i:Interaction.Triggers>
                                        <i:EventTrigger EventName="LostFocus">
                                            <galaExtras:EventToCommand Command="{Binding SearchCriteriaChangedCommand, Mode=OneWay}"></galaExtras:EventToCommand>
                                        </i:EventTrigger>
                                    </i:Interaction.Triggers>
                                </TextBox>
                                <Button Content="Paste Acct"></Button>
                            </StackPanel>
                        </localControls:FormElement>
    
                        <localControls:FormElement LabelText="Acct Level Detail:" Grid.Row="0" Grid.Column="4" >
                            <CheckBox x:Name="chkAcctLevelDetail" VerticalAlignment="Center" 
                                      IsChecked="{Binding AcctLevel_Detail_IsChecked, Mode=TwoWay}">
                                <i:Interaction.Triggers>
                                    <i:EventTrigger EventName="Click">
                                        <galaExtras:EventToCommand Command="{Binding SearchCriteriaChangedCommand, Mode=OneWay}"></galaExtras:EventToCommand>
                                    </i:EventTrigger>
                                </i:Interaction.Triggers>
                            </CheckBox>
                        </localControls:FormElement>
    
                        <localControls:FormElement LabelText="Coupon:" Grid.Row="1" Grid.Column="2">
                            <StackPanel Orientation="Horizontal">
                                <TextBox x:Name="txtCouponFrom" Width="80" Text="{Binding Coupon_From_Text, Mode=TwoWay}" >
                                    <i:Interaction.Triggers>
                                        <i:EventTrigger EventName="LostFocus">
                                            <galaExtras:EventToCommand Command="{Binding SearchCriteriaChangedCommand, Mode=OneWay}"></galaExtras:EventToCommand>
                                        </i:EventTrigger>
                                    </i:Interaction.Triggers>
                                </TextBox>
                                <TextBlock Text="To" Margin="3,0,3,0"></TextBlock>
                                <TextBox x:Name="txtCouponTo" Width="80" Text="{Binding Coupon_To_Text, Mode=TwoWay}" >
                                    <i:Interaction.Triggers>
                                        <i:EventTrigger EventName="LostFocus">
                                            <galaExtras:EventToCommand Command="{Binding SearchCriteriaChangedCommand, Mode=OneWay}"></galaExtras:EventToCommand>
                                        </i:EventTrigger>
                                    </i:Interaction.Triggers>
                                </TextBox>
                            </StackPanel>
                        </localControls:FormElement>
    
                        <localControls:FormElement LabelText="CUSIP:" Grid.Row="1" Grid.Column="3">
                            <StackPanel Orientation="Horizontal">
                                <TextBox x:Name="txtCUSIP" Width="50" Text="{Binding CUSIPS_Text, Mode=TwoWay}" >
                                    <i:Interaction.Triggers>
                                        <i:EventTrigger EventName="LostFocus">
                                            <galaExtras:EventToCommand Command="{Binding SearchCriteriaChangedCommand, Mode=OneWay}"></galaExtras:EventToCommand>
                                        </i:EventTrigger>
                                    </i:Interaction.Triggers>
                                </TextBox>
                                <Button x:Name="btnPasteCUSIP" Content="Paste CUSIP"></Button>
                            </StackPanel>
                        </localControls:FormElement>
    
                        <localControls:FormElement LabelText="Ex CUSIP:" Grid.Row="1" Grid.Column="4">
                            <StackPanel Orientation="Horizontal">
                                <TextBox x:Name="txtExCUSIP" Width="80" Text="{Binding ExCUSIPS_Text, Mode=TwoWay}"  >
                                    <i:Interaction.Triggers>
                                        <i:EventTrigger EventName="LostFocus">
                                            <galaExtras:EventToCommand Command="{Binding SearchCriteriaChangedCommand, Mode=OneWay}"></galaExtras:EventToCommand>
                                        </i:EventTrigger>
                                    </i:Interaction.Triggers>
                                </TextBox>
                                <Button x:Name="btnPasteExCUSIP" Content="Paste CUSIP"></Button>
                            </StackPanel>
                        </localControls:FormElement>
    
                        <localControls:FormElement LabelText="Broker ID:" Grid.Row="2" Grid.Column="2">
                            <TextBox x:Name="txtBrokerID" Width="150" Text="{Binding BrokerIDs_Text, Mode=TwoWay}"  >
                                <i:Interaction.Triggers>
                                    <i:EventTrigger EventName="LostFocus">
                                        <galaExtras:EventToCommand Command="{Binding SearchCriteriaChangedCommand, Mode=OneWay}"></galaExtras:EventToCommand>
                                    </i:EventTrigger>
                                </i:Interaction.Triggers>
                            </TextBox>
                        </localControls:FormElement>
    
                        <localControls:FormElement LabelText="Reserved By: " Grid.Row="2" Grid.Column="3">
                            <ComboBox x:Name="cbReservedBy" Width="150" 
                                      SelectedValue="{Binding ReservedByCode_SelectedValue, Mode=TwoWay}" 
                                      ItemsSource="{ Binding Reserved_By_ItemsSource}" >
                                <i:Interaction.Triggers>
                                    <i:EventTrigger EventName="SelectionChanged">
                                        <galaExtras:EventToCommand Command="{Binding SearchCriteriaChangedCommand, Mode=OneWay}"></galaExtras:EventToCommand>
                                    </i:EventTrigger>
                                </i:Interaction.Triggers>
                            </ComboBox>
                        </localControls:FormElement>
    
                        <localControls:FormElement LabelText="Exclude *HOLD*:" Grid.Row="2" Grid.Column="4">
                            <CheckBox x:Name="chkExcludeHold" VerticalAlignment="Center"
                                      IsChecked="{Binding Exclude_HOLD_IsChecked }"
                                      ></CheckBox>
                        </localControls:FormElement>
    
                        <localControls:FormElement LabelText="Maturity:" Grid.Row="3" Grid.Column="2">
                            <ComboBox x:Name="cbMaturityDates" Width="150" 
                                      SelectedValue="{Binding MaturityDates_SelectedValue, Mode=TwoWay}" 
                                      ItemsSource="{Binding MaturityDates_ItemsSource}"
                                      >
                                <i:Interaction.Triggers>
                                    <i:EventTrigger EventName="SelectionChanged">
                                        <galaExtras:EventToCommand Command="{Binding SearchCriteriaChangedCommand, Mode=OneWay}"></galaExtras:EventToCommand>
                                    </i:EventTrigger>
                                </i:Interaction.Triggers>
                            </ComboBox>
                        </localControls:FormElement>
    
                        <localControls:FormElement LabelText="OFace:" Grid.Row="3" Grid.Column="3">
                            <StackPanel Orientation="Horizontal">
                                <TextBox x:Name="txtOFaceFrom" Width="80" Text="{Binding OFace_From_Text, Mode=TwoWay}" >
                                    <i:Interaction.Triggers>
                                        <i:EventTrigger EventName="LostFocus">
                                            <galaExtras:EventToCommand Command="{Binding SearchCriteriaChangedCommand, Mode=OneWay}"></galaExtras:EventToCommand>
                                        </i:EventTrigger>
                                    </i:Interaction.Triggers>
                                </TextBox>
                                <TextBlock Text="To" Margin="3,0,3,0" ></TextBlock>
                                <TextBox x:Name="txtOFaceTo" Width="80" Text="{Binding OFace_To_Text, Mode=TwoWay}" >
                                    <i:Interaction.Triggers>
                                        <i:EventTrigger EventName="LostFocus">
                                            <galaExtras:EventToCommand Command="{Binding SearchCriteriaChangedCommand, Mode=OneWay}"></galaExtras:EventToCommand>
                                        </i:EventTrigger>
                                    </i:Interaction.Triggers>
                                </TextBox>
                            </StackPanel>
                        </localControls:FormElement>
    
                        <localControls:FormElement LabelText="CF:" Grid.Row="3" Grid.Column="4">
                            <StackPanel Orientation="Horizontal">
                                <TextBox x:Name="txtCFFrom" Width="80" Text="{Binding CF_From_Text, Mode=TwoWay}" >
                                    <i:Interaction.Triggers>
                                        <i:EventTrigger EventName="LostFocus">
                                            <galaExtras:EventToCommand Command="{Binding SearchCriteriaChangedCommand, Mode=OneWay}"></galaExtras:EventToCommand>
                                        </i:EventTrigger>
                                    </i:Interaction.Triggers>
                                </TextBox>
                                <TextBlock Text="To" Margin="3,0,3,0" ></TextBlock>
                                <TextBox x:Name="txtCFTo" Width="80" Text="{Binding CF_To_Text, Mode=TwoWay}" >
                                    <i:Interaction.Triggers>
                                        <i:EventTrigger EventName="LostFocus">
                                            <galaExtras:EventToCommand Command="{Binding SearchCriteriaChangedCommand, Mode=OneWay}"></galaExtras:EventToCommand>
                                        </i:EventTrigger>
                                    </i:Interaction.Triggers>
                                </TextBox>
                            </StackPanel>
                        </localControls:FormElement>
    
                        <localControls:FormElement LabelText="Settled CF:" Grid.Row="4" Grid.Column="2">
                            <StackPanel Orientation="Horizontal">
                                <TextBox x:Name="txtSettledCFFrom" Width="80" Text="{Binding Settled_CF_From_Text, Mode=TwoWay}">
                                    <i:Interaction.Triggers>
                                        <i:EventTrigger EventName="LostFocus">
                                            <galaExtras:EventToCommand Command="{Binding SearchCriteriaChangedCommand, Mode=OneWay}"></galaExtras:EventToCommand>
                                        </i:EventTrigger>
                                    </i:Interaction.Triggers>
                                </TextBox>
                                <TextBlock Text="To" Margin="3,0,3,0" ></TextBlock>
                                <TextBox x:Name="txtSettledCFTo" Width="80" Text="{Binding Settled_CF_To_Text, Mode=TwoWay}" >
                                    <i:Interaction.Triggers>
                                        <i:EventTrigger EventName="LostFocus">
                                            <galaExtras:EventToCommand Command="{Binding SearchCriteriaChangedCommand, Mode=OneWay}"></galaExtras:EventToCommand>
                                        </i:EventTrigger>
                                    </i:Interaction.Triggers>
                                </TextBox>
                            </StackPanel>
                        </localControls:FormElement>
    
                        <localControls:FormElement LabelText="Description:" Grid.Row="4" Grid.Column="3">
                            <TextBox x:Name="txtDescription" Width="150" Text="{Binding Description_Text, Mode=TwoWay}" >
                                <i:Interaction.Triggers>
                                    <i:EventTrigger EventName="LostFocus">
                                        <galaExtras:EventToCommand Command="{Binding SearchCriteriaChangedCommand, Mode=OneWay}"></galaExtras:EventToCommand>
                                    </i:EventTrigger>
                                </i:Interaction.Triggers>
                            </TextBox>
                        </localControls:FormElement>
    
                        <localControls:FormElement LabelText="Duration:" Grid.Row="4" Grid.Column="4">
                            <StackPanel Orientation="Horizontal">
                                <TextBox x:Name="txtDurationFrom" Width="80" Text="{Binding Duration_From_Text, Mode=TwoWay}">
                                    <i:Interaction.Triggers>
                                        <i:EventTrigger EventName="LostFocus">
                                            <galaExtras:EventToCommand Command="{Binding SearchCriteriaChangedCommand, Mode=OneWay}"></galaExtras:EventToCommand>
                                        </i:EventTrigger>
                                    </i:Interaction.Triggers>
                                </TextBox>
                                <TextBlock Text="To" Margin="3,0,3,0" ></TextBlock>
                                <TextBox x:Name="txtDurationTo" Width="80" Text="{Binding Duration_To_Text, Mode=TwoWay}" >
                                    <i:Interaction.Triggers>
                                        <i:EventTrigger EventName="LostFocus">
                                            <galaExtras:EventToCommand Command="{Binding SearchCriteriaChangedCommand, Mode=OneWay}"></galaExtras:EventToCommand>
                                        </i:EventTrigger>
                                    </i:Interaction.Triggers>
                                </TextBox>
                            </StackPanel>
                        </localControls:FormElement>
    
                        <localControls:FormElement LabelText="Repo:" Grid.Row="5" Grid.Column="2">
                            <ComboBox x:Name="cmbRepo" Width="150" 
                                      SelectedValue="{Binding Repo_SelectedValue, Mode=TwoWay}" 
                                      ItemsSource="{Binding Repo_ItemsSource}"
                                      >
                                <i:Interaction.Triggers>
                                    <i:EventTrigger EventName="SelectionChanged">
                                        <galaExtras:EventToCommand Command="{Binding SearchCriteriaChangedCommand, Mode=OneWay}"></galaExtras:EventToCommand>
                                    </i:EventTrigger>
                                </i:Interaction.Triggers>
                            </ComboBox>
                        </localControls:FormElement>
    
                        <localControls:FormElement LabelText="Inv Ind:" Grid.Row="5" Grid.Column="3">
                            <ComboBox x:Name="cmbInvInd" Width="150" 
                                      SelectedValue="{Binding InvInd_SelectedValue, Mode=TwoWay}" 
                                      ItemsSource="{Binding InvInd_ItemsSource}"
                                      >
                                <i:Interaction.Triggers>
                                    <i:EventTrigger EventName="SelectionChanged">
                                        <galaExtras:EventToCommand Command="{Binding SearchCriteriaChangedCommand, Mode=OneWay}"></galaExtras:EventToCommand>
                                    </i:EventTrigger>
                                </i:Interaction.Triggers>
                            </ComboBox>
                        </localControls:FormElement>
    
                        <localControls:FormElement LabelText="Collateral:" Grid.Row="5" Grid.Column="4">
                            <ComboBox x:Name="cmbCollateral" Width="150" 
                                      SelectedValue="{Binding Collateral_SelectedValue, Mode=TwoWay}" 
                                      ItemsSource="{Binding Collateral_ItemsSource}"
                                      >
                                <i:Interaction.Triggers>
                                    <i:EventTrigger EventName="SelectionChanged">
                                        <galaExtras:EventToCommand Command="{Binding SearchCriteriaChangedCommand, Mode=OneWay}"></galaExtras:EventToCommand>
                                    </i:EventTrigger>
                                </i:Interaction.Triggers>
                            </ComboBox>
                        </localControls:FormElement>
    
                        <localControls:FormElement LabelText="Coupon Type:" Grid.Row="6" Grid.Column="2">
                            <ComboBox x:Name="cmbCouponType" Width="150" 
                                      SelectedValue="{Binding CouponType_SelectedValue, Mode=TwoWay}" 
                                      ItemsSource="{Binding CouponType_ItemsSource}"
                                      >
                                <i:Interaction.Triggers>
                                    <i:EventTrigger EventName="SelectionChanged">
                                        <galaExtras:EventToCommand Command="{Binding SearchCriteriaChangedCommand, Mode=OneWay}"></galaExtras:EventToCommand>
                                    </i:EventTrigger>
                                </i:Interaction.Triggers>
                            </ComboBox>
                        </localControls:FormElement>
    
                        <localControls:FormElement LabelText="Security Type:" Grid.Row="6" Grid.Column="3">
                            <ComboBox x:Name="cmbSecurityType" Width="150" 
                                      SelectedValue="{Binding SecurityType_SelectedValue, Mode=TwoWay}" 
                                      ItemsSource="{Binding SecurityType_ItemsSource}"
                                      >
                                <i:Interaction.Triggers>
                                    <i:EventTrigger EventName="SelectionChanged">
                                        <galaExtras:EventToCommand Command="{Binding SearchCriteriaChangedCommand, Mode=OneWay}"></galaExtras:EventToCommand>
                                    </i:EventTrigger>
                                </i:Interaction.Triggers>
                            </ComboBox>
                        </localControls:FormElement>
                    </Grid>
                </GroupBox>
            </DataTemplate>
    Wednesday, September 14, 2011 6:00 PM
  • Wow.  I think I would go nuts if I was being forced to program that way. The best thing I can say about that code is that at least it doesn't have any hungarian notation going on.

    Technically speaking, OnPropertyChanged is part of how data binding works in Silverlight, not MVVM, but since MVVM doesn't work without the data binding I understand the attachment. I noticed you have a list of List instead of ObservableCollection in there, that just makes things worse doesn't it?

    I really don't understand the endless amount of triggers you are having to add. The ViewModel already knows that values were changed based on the main binding, telling the ViewModel separately something that it should already knows seems like double work to me. Of course, I use WCF RIA Services to generate all of my entity code so much of the extra work you are doing is something I don't have to do.

    Here is an example of what I mean:

    <TextBox x:Name="txtCouponTo" Width="80" Text="{Binding Coupon_To_Text, Mode=TwoWay}" >
                                    <i:Interaction.Triggers>
                                        <i:EventTrigger EventName="LostFocus">
                                            <galaExtras:EventToCommand Command="{Binding SearchCriteriaChangedCommand, Mode=OneWay}"></galaExtras:EventToCommand>
                                        </i:EventTrigger>
                                    </i:Interaction.Triggers>
                                </TextBox>

    Why do you need to bind the LostFocus event to the ViewModel to trigger the SearchCriteriaChangedCommand? The ViewModel already knows that SearchCriteriaChanged because the set of the Coupon_To_Text property was called. I would call SearchCriteriaChangedCommand from the set method of the property. To be quite honest about it, I think that is a separation of concerns issue.

    (To your first question, I think that code is testable as is. The test code would instantiate the ViewModel, attach itself to the messenger to listen for the messages, and then call the command. In a real application that I would write there would also be a DomainContext, a DataService, and a IDataService. The constructor of the ViewModel would take in the IDataService instance through MEF. Even then, that would all be setup to be testable.)

    Wednesday, September 14, 2011 6:48 PM
  • To be quite honest about it, I think that is a separation of concerns issue.

    Definitely. My honest opinion is that the entire big example that was just posted really just can't be considered MVVM. It looks like the writer figured out how to get things to work using WPF, but didn't realize how MVVM could simplify and clarify the program.

    This is a silly way of putting it, but let it be known that the presence of the word "Binding" in a XAML file does not mean that MVVM is in use. It means that data binding is in use.

    Wednesday, September 14, 2011 10:16 PM
  • Definitely. My honest opinion is that the entire big example that was just posted really just can't be considered MVVM. It looks like the writer figured out how to get things to work using WPF, but didn't realize how MVVM could simplify and clarify the program.

    To be fair, it is less "the writer figured out" and more "the architect telling the writer what to do figured out".

    The point of MVVM is that it was naturally how Silverlight worked so using MVVM actually makes things easier to create and maintain over time. As MVVM has been used certain situations (i.e. how does the ViewModel alert the View layer that we need to show a messagebox) have been discovered that were harder to handle in MVVM then they should be. To solve those problems libraries like MVVM Light have been created. Any time that the MVVM library tail starts wagging the View/ViewModel dog (like adding a separate event call to every single edit control on a view) then something is wrong. My personal approach is to use the bare minimum. I derive my ViewModel from ViewModelBase (since that gives me RaisePropertyChange methods), I use MEFedMVVM to bind my View, ViewModel, and DataService together, and then I start writing my application.

    Chances are you may not end up using anything else that MVVM Light provides and that is a perfectly good situation to be in. If you do run into something that you can't figure out how to do or just doesn't "feel" right then a good solution may be available to you in the toolkit. The wrong thing to do is to look through everything that Laurent provides in MVVM Light and go searching for ways to use them.

    Wednesday, September 14, 2011 10:51 PM
  • It looks like the writer figured out how to get things to work using WPF, but didn't realize how MVVM could simplify and clarify the program.

    The reason I posted code and issued the challenge is that this entire thread is just talk.  If anything is going to get resolved its going to be backed up by examples in code.  Having said that, Andy why don't you post some code and show us specifically how MVVM can simplify and clarify the program.  

    @Colin,  this is wpf, not silverlight by the way.  The screen is an interactive search.  Every time the user changes a control value a data grid is refreshed.  If you know of an easier way to get it done let me know (EDIT:  post some code :)).  Thanks.

     

    Thursday, September 15, 2011 11:13 AM
  • private string _coupon_From;
    public string Coupon_From
    {
                get { return _coupon_From; }
                set
                {
                            _coupon_From = value;
                            OnPropertyChanged("Coupon_From");
                            UpdateSearchCriteria();
                }
    }
    
    private string _coupon_To;
    public string Coupon_To
    {
                get { return _coupon_To; }
                set
                {
                            _coupon_To = value;
                            OnPropertyChanged("Coupon_To");
                            UpdateSearchCriteria();
                }
    }
    <localControls:FormElement LabelText="Coupon:" Grid.Row="1" Grid.Column="2">
    <StackPanel Orientation="Horizontal">
    <TextBox Width="80" Text="{Binding Coupon_From, Mode=TwoWay}" />
    <TextBlock Text="To" Margin="3,0,3,0"/>
    <TextBox Width="80" Text="{Binding Coupon_To_Text, Mode=TwoWay}" />
    </StackPanel>
    </localControls:FormElement>

    It was already pointed out that you just need to use the Setters of the properties to handle side effects

    The other changes I tried to show is that properties of the view model should be names like other properties of objects that that aren't used in a view. The names in the big example looked smilar to what you would see as names of form elements such as "couponToTextBox"

    The reason I clipped out the names of the controls in the XAML is to point out that often the solution is often simple enough where the controls never need to be referenced by name

    Thursday, September 15, 2011 12:14 PM
  • Tim,

    Exactly!!!  Apparently some people have WAY too much free time on their hands or have some vested interest in promoting MVVM ... it almost sounds like more inter department rivalry at Microsoft where heads of departments/project are fighting for their projects to get funded and resources allocated.

    ...in the meantime, real developers have real problems to address in the shortest possible time frame ... and guess what, molding oneself to some righteous way of how it "should" be done so that testing is easier just doesn't hack it in my world for short term nor long term ... there is NO ROI in MVVM ... let me repeat this again, NO ROI, it's dead, will not happen, end of line.

    Sadly though, I'm sure Microsoft will adapt it, force it on everyone like it or not, and call it a day.  Aren't we blessed.

    Rob

    Thursday, September 15, 2011 1:02 PM
  • @Colin,  this is wpf, not silverlight by the way.  The screen is an interactive search.  Every time the user changes a control value a data grid is refreshed.  If you know of an easier way to get it done let me know (EDIT:  post some code :)).  Thanks.

    Ah, that explains why you were using a Yes/No combobox in your version of the combobox sample. I had wondered at the time but decided it was unimportant. Generally I agree with the code that Andy posted including not putting names on the controls. My only hesitation is that I have never written a WPF application myself so it is possible that I am missing something.

    Thursday, September 15, 2011 1:24 PM
  • Sadly though, I'm sure Microsoft will adapt it, force it on everyone like it or not, and call it a day.  Aren't we blessed.

    I believe that particular concern was answered yesterday on Twitter:

    rlarno: @Pete_Brown Not using Command pattern => BAD BAD BAD! I was hoping you'd put MVVM right in the tool support like MVC
    Pete_Brown: @rlarno not all developers agree and it can be a barrier to entry

    Thursday, September 15, 2011 1:31 PM
  • Andy, I still need to handle an event on the view to in order to detect input from the user.  That means for every control I must wire up some event handler.  Actually, since I'm calling the same event from almost every control, my code actually shows LESS code than would be requred if every control had its own command property.  Also, if I call UpdateSearchCriteria from the setter I cannot set properties on the viewmodel and update the view from UpdateSearchCritera without winding up in a loop or creating a secondory calls to OnPropertyChanged (if I change the private field).  On its face it appears what you suggested is a good idea but I thought about it also earlier and it causes many more problems than it solves.  For the record, the way I implemented MVVM is per the suggested pattern.  If it is truly simplier and clearer I should not have to even think about design concessions like you just recommended.  In an earlier post you indicated something about the imporantantance separation of concerns, yet here you suggest I mix view logic with business logic at a very granular level.   Sometimes it is easy to miss the forest for the trees :)

    Sorry but I dont understand what you said about control names.  I don't address any controls by name from the viewmodel if that is what you mean.

    Also, so we dont get too far off track, lets remember we are looking at the amount of code required to handle an event via MVVM vs the old way.  When you look at a XAML event handler you see right away what method handles the event.  When you use MVVM you only see the command the event is bound to.  You still have an extra step to get to the method that handles the event.

    Thursday, September 15, 2011 1:44 PM
  • To your point about avoiding infinte loops, I do have code like that and here is what I do:

    bool _updatingSearchCriteria = false;
    void UpdateSearchCriteria()
    {
        if (_updatingSearchCriteria)
            return;
        try
        {
            _updatingSearchCriteria = true;
    //do stuff
        finally
        {
            _updatingSearchCriteria = false;
        }
    }

    Thursday, September 15, 2011 2:00 PM
  • To your point about avoiding infinte loops, I do have code like that and here is what I do:

    Says the guy who would go nuts if he was forced to code like me!!  LOL You are killing me Colin!

    That is exactly the kind of code I have in other places in my VM and I hate it! 

    For example, changing the selectedvalue of a combox causes its command to fire which causes a nasty loop.  I have the kind of comment you see below in many places in my code.  Its ugly and not elegant and complex and confusing!  We are getting to the core of why MVVM is seriously oversold.  The kind of code you see here is horrific when used in a large application.  When I checked this code in I made a specific point to tell my team members about it so they would not think I was a flaming amature (well maybe I am but lets not tell them LOL).

     protected void SearchCriteriaChanged()
            {
                // EventToCommand is bound to the SelectionChanged event on comboboxes.  When a filter 
                // is applied, changing the value causes this method to be called reentranly.  
                // The SearchCriteriaChangedCanExecute flag is used to prevent that.
    
                if (!SearchCriteriaChangedCanExecute)
                    return;

     

    Thursday, September 15, 2011 3:17 PM
  • I don't know what's worse, the fact it was actually considered at all, or the fact that MS have become so "righteous"??

    "all developers" -- sorry but Microsoft see a very small small small fraction of the developer population, certainly NOT ALL, not even close.

    Like I've been saying all along, stop "guessing" on how things "should be done" and provide flexible tools that let developers get things done as fast as possible with good ROI --- please Microsoft, stop being so "righteous", I don't want it, have no need for it, can't sell it, can't get it funded, so please stop and focus on tools that do NOT restrict, but expand.

    Rob 

    Thursday, September 15, 2011 4:12 PM
  • Says the guy who would go nuts if he was forced to code like me!!  LOL You are killing me Colin!

    Yes, if I was writing code that looked like the code you showed I would find a better way to do it. You asked how me I would do it in a simpler way and I told you. You decided to laugh at me about it. That is fine, mock me if you want, it doesn't matter to me.

    Lets recap:

    1. Is MVVM oversold? Yes.
    2. Is Microsoft trying to force everyone to use MVVM? No.
    3. Are you having a hard time using MVVM in your application? Yes.
    4. Am I having a hard time using MVVM in my applications? No.
    5. Is my application the same as your application? No.
    6. Will I continue to use and recommend MVVM to others? Yes.
    7. Do I care if anyone follows my recommendations to use MVVM? No.

    Is there anything else to talk about here?

     

    Thursday, September 15, 2011 4:19 PM
  • Yes, if I was writing code that looked like the code you showed I would find a better way to do it. You asked how me I would do it in a simpler way and I told you. You decided to laugh at me about it. That is fine, mock me if you want, it doesn't matter to me.

    I'm not laughing at anyone. I just think its ironic that the solutions being proposed are as onerous than the problems they are supposed to solve.

    I gave a detailed response to Andy that argues that the design you propose is not only not simpler but is in fact more complex than what I'm using.

     

    Thursday, September 15, 2011 4:47 PM
  • I still need to handle an event on the view to in order to detect input from the user

    The binding is what detects user input and sets the updated value of the control by using the setter in the view model. No event needed.

    Also, if I call UpdateSearchCriteria from the setter I cannot set properties on the viewmodel and update the view from UpdateSearchCritera without winding up in a loop or creating a secondory calls to OnPropertyChanged (if I change the private field). 

    I don't have your code in front of me, and although I'm interested in explaining how it would work, I obviosuly can't rewrite it just to make a point, but honestly I don't think you would run into this issue. I think I've done something similar, and there are probably WPF MVVM examples of apps that do something similar to yours that you could look at.

    Friday, September 16, 2011 9:29 AM
  • So this is a discussion that will probably happen until the perfection or removal of MVVM as a whole, as evidenced by the fact that this particular discussion started nearly 2.5 years ago. I love to stir up old pots so I figured I'd throw my 2 pennies in a listen to them clink around.

    I feel the pain everyone does about MVVM. The fact is that without the use of libraries (per Colin) then most programming options are limited. Before anyone trolls and says something akin to "You don't have to have libraries to do anything in <insert language here>", I'd like to remind you that you don't HAVE to use anything for XAML either. In all cases, you can create your own things to help you do other things better and faster (your own library?) but that would just be spending resources that have already been spent.

    My biggest hang up with the adoption of MVVM was simply the hoops you have to jump through for everything. Take, for example, the complexity to bind a command to a button. Something that simple (double click that bad boy in the designer) in WinForms was extremely compounded by removing the code from the UI level. Yeah, I could have double clicked it in XAML and did it in code behind, but I'm just plain stubborn and wanted to "enjoy" what MVVM had to offer.

    Enter Caliburn and the world of naming conventions and dependency injections. If you are being forced to chew on MVVM then please take the time to learn the Caliburn (http://caliburnmicro.codeplex.com/) framework. This bad boy has literally saved me hundreds of hours of coding. Now, that save button mentioned above is as simple as naming the method in your VM the same as the button in the XAML. So if I have a button named SaveMe and a method in my VM named SaveMe() then Caliburn automagically (using a fair dose of reflection) links the two together. Also (as long as you're using the subject<> attributes for dependency injection) your properties on your model will automagically link up to your xaml using similair naming conventions. If I have a property in my model, for this view, named FirstName then I can name my textbox Subject_FirstName and the two are automagically bound together.

    I hope that this introduces someone else struggling with adopting MVVM to a cleaner way of doing things.

    Saturday, May 05, 2012 11:42 AM
  • You might like to know about http://mvvmfx.codeplex.com/

    It's a library of MVVM stuff fow Windows Forms:
    1) a databinding library with converters that can also bind an Action to a property change
    2) a command binding library that can bind an Action to any input event of any UI component

    Wednesday, June 13, 2012 6:50 PM
  • MVVM is SO GOOD that WPF and SL are now dead technologies??  Please lets hope that MVVM doesn't drive other MS development technology implementations.

    If I hear one more thing about "separation" I think I'll have to slap someone ... it's code and separation isn't necessary!  Get OVER YOURSELF already ... that's great, MVVM works for you and "fits" how you "think" logic should be separated.  What I object to is that the structure/architecture of a language/technology is being changed so that MVVM works better with that technology.  Like other's have said WPF had a better implementation that fit MVVM and WPF (I've encountered zero WPF projects so far and have never needed WPF) is even more dead than SL.

    Yes MVVM is really just a conceptal method of UI implementations, but it got so ugly to implement that templates got created just for MVVM.

    How much of the MVVM XAML code (yes that's right CODE) are you going to use in HTML5?  Would that be none -- so much for re-use.

    But the real point here is that MVVM is dictating a technology implementation (SL/WPF) -- if you really "believe" in MVVM then you know that SHOULD NOT be the case.  By all means, live your world of MVVM, but do NOT handicap/complicate an implementation (like SL) just to make MVVM work better.

    Rob

    Wednesday, August 15, 2012 4:11 PM
  • MVVM is SO GOOD that WPF and SL are now dead technologies?

    You think one caused the other? WPF is dead? You see all that XAML in Windows 8, that's WPF in another form.

    Please lets hope that MVVM doesn't drive other MS development technology implementations.

    It never did.

    (I've encountered zero WPF projects so far and have never needed WPF)

    I've never coded in Objective-C, must be dead.

    that templates got created just for MVVM.

    The existence of templates is a sign of ugliness?

    How much of the MVVM XAML code (yes that's right CODE) are you going to use in HTML5?

    I could take a Viewmodel from Silverlight and move it to a WPF or Metro app and vice versa. Are you making some sort of bizarre HTML5 doesn't support c# or databinding argument here?

    But the real point here is that MVVM is dictating a technology implementation (SL/WPF)

    Um, if you don't like it, don't use it. WPF supported commanding before people were even talking about MVVM. You're acting like Microsoft has disabled code behinds in VS 2012.

    but do NOT handicap/complicate an implementation (like SL) just to make MVVM work better.

    You know how much sense your entire post made. ZERO. It read like some sort of bizarre rage against a poorly understood technology with no basis in reality. Want to prove me wrong? Name one thing, just one thing where the mere existence of MVVM and Microsoft's supposed complicating Silverlight has prevented you from doing everything in a code behind. I really hope you come up with something, because I can guarantee you, your argument is going to get ripped to shreds.

    Wednesday, August 15, 2012 6:44 PM
  • You see all that XAML in Windows 8, that's WPF in another form

    You see all that WPF, it's another form of WindowsForms.designer ... not even sure what your point is here?  Are you suggesting XAML is a good thing or a bad thing ... anyway, what I can assure is that my WindowsForms applications compile about 1000X times faster than SL or WPF... have plenty of re-use ... don't bring VS 2010 to it's knees ... and the performances is MUCH better.  But hey, MVVM is the "correct" way right ... even if it kills compiles and application performance??  Have you even tried to edit XAML in VS 2010 ... it's a painful experience and certainly doesn't "speed" up my development time ... or even in Blend, OMG talk about the slowest and most buggy application ever released by Microsoft -- I feel sorry for any designer that would have to punish themselves with Blend.  But even direct coding in XAML is slow and intellisense sometimes just goes out to lunch (especially with enumerated DependencyProperties).

    It never did.

    Joking right?

    I've never coded in Objective-C, must be dead.

    I've never coded assembly (well at least not for x86) and as best I can tell, very few people still do.  But if you want a guage of usage/adoption, just search for books on WPF, then search on books for HTML5 ... basics of supply and demand, WPF is not in demand hence not many books.

    The existence of templates is a sign of ugliness?

    Yes, it means lots of boiler code, repeated over and over.

    Um, if you don't like it, don't use it. WPF supported commanding before people were even talking about MVVM. You're acting like Microsoft has disabled code behinds in VS 2012.

    Windows Forms supported commanding so?  I "Try" not to use MVVM, but when you build a technology like WPF and SL that is structured to fit in with MVVM abstractions, it's hard to avoid.

    Name one thing, just one thing where the mere existence of MVVM and Microsoft's supposed complicating Silverlight has prevented you from doing everything in a code behind.

    Nothing "preventing" me, I never said there was??  What's NOT happening is technology progression in a direction where people don't want MVVM.  What I said is handicaps/complicate ... that isn't "preventing" - far from it.  But if you want a good example, DataTemplates, Data binding is horribly slow compare to more other methods, Animations, Control Focus, and more - improved in SL5 but still a ways to go, too bad we'll never see and SL6.

    And then the complete lack of existances of SqlClient or any direct database binding -- why?  The excuse is that it would make the SL5 download too big -- give me a break, THE ONE TIME download is the concern???  At today's internet speeds it's a non-issue and since SL doesn't work on most mobile OS's it's even less important of an issue.  The real reason is more likely because it would encourage less separation which would be anti-MVVM.

    And then there is the "maintainability" and "re-use" arguement ... not a single quantitive shred of evidence to support better ROI from initiate development to long term maintenance -- I haven't seen a designer yet, that hasn't needed to understand what he/she is getting for "their view".  Sure, a designer can happily go along with whatever View they want but the lack of NOT understanding what exists in the other layers can and does produce slow UIs and worky UIs ... so the attempt at separation is bad for performance and the designs end up in a "black hole"  -- end users don't care about MVVM or if the application has met some set of standards (and I've yet to see any two application follow MVVM to the intended specification).

    Since when has it been more efficient to produce ViewModel code and lots of different View code vs. coming up with a single joint design at the onset of a project??  End users rarely like UI changes, they hate slow performing apps -- it's like MVVM pudits got so consumed abstraction and separation that they forget the most important aspect of an application.

    Wednesday, August 15, 2012 8:01 PM