none
Seperate ViewModel and View without using Code Behind

    Frage

  • I am looking at seperating Views from their respecting ViewModels without using any code behind. On obstacle in that endevour is the commanding framework. Currently, I am using the static approach:

    • That is, I have a static class MainCommands containing all static command properties that my application supports
    • In the constructor of each dialog I am binding to the respective command property to the corresponding method, like so:
    this.CommandBindings.Add(new CommandBinding(ApplicationCommands.New,
                        (s, e) => this.New_CommandExecuted(s, e),
                        (s, e) => this.CanExecute_IfNoBatchRuns(s, e)));

    Now, I noticed that this can only be done in the code behind because the this.CommandBindings bit is otherwsie not available(?).

    I have also looked at other options such as the cool RelayCommand class that originated from Josh Smith's work. But with that class I am not sure how to seperate View and ViewModel without using codebehind. Plus, I need a solution that supports Short-Keys and InputGetsures when using a command in a GUI items that supports it (eg.: MenuItem).

    What is the current method to go about this? Are their any samples I could look at? Here is a summary list of the requirements I am after:

    • Seperate View and ViewModel without using code behind and using commands to expose ViewModel program logic functionality to the view
    • Support short keys and input gestures in GUI items such as the MenuItem like with the RoutedUICommand
    • Typ geändert Dirkster9999 Donnerstag, 15. März 2012 16:41
    Dienstag, 6. März 2012 16:37

Antworten

  • Relaycommand just works just the same as a command.

    So you can make your command a resource and bind to that as a staticresource, attach gestures to that or you can bind it directly in the menuItem and set InputBindings.

                <Menu>
                    <MenuItem Name="New" Header="New Whatever" Command="a relay command">
                        <MenuItem.InputBindings>
                            <KeyBinding Key="N" Modifiers="Control" />
                        </MenuItem.InputBindings>
                   </MenuItem>
                </Menu>


    • Bearbeitet Andy ONeill Mittwoch, 7. März 2012 10:40
    • Als Antwort markiert Dirkster9999 Donnerstag, 15. März 2012 16:41
    Mittwoch, 7. März 2012 10:34
  • BTW there is absolutely nothing wrong with putting a few command calls in CODE BEHIND, so with that, you shouldn't really have a problem there.  You don't need any stinkin' relay command either, rather you can abstract ALL of your commands to a COMMAND folder.  In that folder implement your STATIC command classes, and just call them passing in any parms. you want.

    Sometimes I feel all of these tricks in MVVM cause a lot of frustration only because they are too complex for the simple things at hand.  If we look at what MSFT does with commands, they make them all publically accessable at start of program.  This means they are static and they are NOT in anyway tightly coupled.  This is the same thing you'd accomplish by moving some of these commands to their own folder.


    JP Cowboy Coders Unite!

    • Als Antwort markiert Dirkster9999 Donnerstag, 15. März 2012 16:42
    Freitag, 9. März 2012 13:27

Alle Antworten

  • >> I am looking at seperating Views from their respecting ViewModels without using any code behind.

    Well this is just opinion but I suggest you ask yourself "What am I accomplishing by doing this?" and "Are the benefits worth the costs?".  You may have already done this and if so I aplogize.   I know this does not answer your question and I dont have an answer, just a bit of adivse based on experience. 

    Dienstag, 6. März 2012 18:37
  • Yes, you can connect a view to a viewmodel with no code behind.

    Expose the command from the viewmodel using relaycommand in the viewmodel.

    Bind to the command in xaml.

    Personally, I usually set the datacontext of the view to the viewmodel in the view constructor.

    You can altenatively instantiate each separately and set the datacontext extenally.  You then have created a complication for yourself because you have to dispose of your viewmodel somewhere.


    Dienstag, 6. März 2012 19:19
  • I have not done it yet and I am not going to if there is no good solution - the benefit is that I am more flexible in choosing the view that I am using - right now I am using a home grown version but I would like to convert to the new version of Avalon Dock. I can already do it in the space of a few hours work but I am still wondering whether there is a better design approach to select a view in a flexible manner while maintaining a consistent design...in a nutshell: I am really asking for a solution not an opinion (because I got my own opinion too)

    Dienstag, 6. März 2012 21:34
  • Hi Andy,

    I know I can do it with RelayCommand as I pointed out in the initial post - but what about input gestures and short keys? Is there a solution that includes them as well or is it either

    • code behind for the command binding and short keys

      OR

    • RelayCommand and no input gestures and short keys?
    Dienstag, 6. März 2012 21:38
  • You can fire commands with gestures and you can bind commands.  It's not an issue.
    Dienstag, 6. März 2012 21:44
  • Hi Andy,

    can you give me sample code to get me started? To me its an issue because I do not know how to do it :) otherwise I would not have asked. Thanks a lot for your patients :)

    I am looking for design that lets me use the commanding just like using the RoutedUICommand - that is - I can do something like <MenuItem Command="{Binding cmd:MyCommand}" /> and the MenuItem automatically locates the correct Header text and short keys.

    I can also use it with a button and bind the button text to the text of the RoutedUICommand etc... with RelayCommand I have no clue about how this can be implemented. Please give me more than: "yes sure you can do it"

    Dienstag, 6. März 2012 22:50
  • Dirk;

      Don't hamstring yourself too much, You can bind commands in xaml is you include a reference to the class and you create a static instance withing the XAMLS resources section...  Then the command bindings can all be applied via the XAML editor which will use intellisense to help you.

    Everyone has their own opinions on MVVM, and mine are these: 1) You can have code in view code behind.  Try to limit it to GUI Related things etc.  Make it a goal to just do GUI stuff there.  You can even, if you want kick off commands but you miss out on WPF GUI features of binding commands in XAML instead.  When a command is bound in XAML then say on a button click it won't be enabled until the command is done!  All pretty much automated for you!

    I personally don't care for the relay command much but in that teaching they are used to boomerang a command back to view model.  Which is ok.  The viewmodel then is the brains for coordinating collections, telling the model when to get the data etc.  The View then just Binds to the collections in the Viewmodel.


    JP Cowboy Coders Unite!

    Dienstag, 6. März 2012 23:01
  • This article demonstrates how to use relaycommand in much more detail than I'm likely to put in a post.

    http://msdn.microsoft.com/en-us/magazine/dd419663.aspx

    You are pretty much binding to a method exposed from the viewmodel, just doing it in a bit of an indirect way.

    Mittwoch, 7. März 2012 09:20
  • Hi Andy,

    I am aware of that article. Its great but it does not solve my problem (unless I am missing something). My problem is not with using the RelayCommand class. My problem is with using the RelayCommand and still being able to use short cuts, input gestures, and command text as described in my last post.

    I do not think that question is answered anywhere in Josh's article or am I missing something?

    Mittwoch, 7. März 2012 09:33
  • Relaycommand just works just the same as a command.

    So you can make your command a resource and bind to that as a staticresource, attach gestures to that or you can bind it directly in the menuItem and set InputBindings.

                <Menu>
                    <MenuItem Name="New" Header="New Whatever" Command="a relay command">
                        <MenuItem.InputBindings>
                            <KeyBinding Key="N" Modifiers="Control" />
                        </MenuItem.InputBindings>
                   </MenuItem>
                </Menu>


    • Bearbeitet Andy ONeill Mittwoch, 7. März 2012 10:40
    • Als Antwort markiert Dirkster9999 Donnerstag, 15. März 2012 16:41
    Mittwoch, 7. März 2012 10:34
  • Yes as Andy and I have both said, do the command binding in the XAML.... This gets you what you want.

    JP Cowboy Coders Unite!

    Mittwoch, 7. März 2012 13:46
  • Hi All,

    Thanks all for the excellent discussion in the MSDN forum.

    That's the exact same quesiton I had when I went through MVVM articles. If I didn't get it wrong, the InputBinding won't work for RelayCommand because it cannot bind to viewmodel.

    My solution is to use an attached property where you can specify the input gestures, then you can bind the attached property to the relaycommand.

    Best regards,


    Min Zhu [MSFT]
    MSDN Community Support | Feedback to us

    Freitag, 9. März 2012 01:34
    Moderator
  • Hi Everyone,

    thanks a lot for your input. Min's comment reflects at last what I was looking for. But now I am wondering why using an attached property if you have the source? I am thinking: Extend the RelayCommand class with an InputGesture and Text dependency property and see whether a menu item will pick it up automatically - if not - use the binding to do it.

    I'll get back here in a few days to let you guys know.

    Cheers Dirkster

    Freitag, 9. März 2012 13:17
  • BTW there is absolutely nothing wrong with putting a few command calls in CODE BEHIND, so with that, you shouldn't really have a problem there.  You don't need any stinkin' relay command either, rather you can abstract ALL of your commands to a COMMAND folder.  In that folder implement your STATIC command classes, and just call them passing in any parms. you want.

    Sometimes I feel all of these tricks in MVVM cause a lot of frustration only because they are too complex for the simple things at hand.  If we look at what MSFT does with commands, they make them all publically accessable at start of program.  This means they are static and they are NOT in anyway tightly coupled.  This is the same thing you'd accomplish by moving some of these commands to their own folder.


    JP Cowboy Coders Unite!

    • Als Antwort markiert Dirkster9999 Donnerstag, 15. März 2012 16:42
    Freitag, 9. März 2012 13:27
  • Hi Min,

    I think I got your solution wrong at first -because I thought you wanted to extend the RelayCommand with an attached property - but now I recognized that you want to extend the MenuItem (or any other GUI control) with an attached property and use that to kick of a command. Could you share some sample code on that?

    I got as far as playing with dependency properties in the RelayCommand class. And extending the class with a Text property was no problem, although, it not picked up automatically as with the RoutedUICommand when used in the MenuItem, it can still be bound and would thus, be OK. But I got nowhere near a useful implementation with the KeyBinding or display of it in the menu itself...

    Cheers Dirkster

    Samstag, 10. März 2012 23:25
  • I've done some thinking and some tinkering and some more thinking and arrived at a similar conclusion. You either have to use RoutedUICommand with a minimal code behined or you can use RelayCommand implmented in the ViewModel. The later case requires to specify keyboard shortcusts and command text in the view - seperated from the ViewModel.

    So, both techniques have there drawbacks and putting a command with gestures and shortcuts in the viewmodel is not necessarily and advantage. Thanks for your patience.

    Donnerstag, 15. März 2012 16:36
  • Excellent and thanks for feedback!

    JP Cowboy Coders Unite!

    Donnerstag, 15. März 2012 17:42
  • The most efficient solution to is to use/develop the XAML -markup extension where you can solve this by delegating create instance of the “relay” to the XAML markup extension.

    Here are links:

    Samstag, 18. Mai 2013 17:56