0

I'm developing a simple contact manager for WP 8.1. The MV is a list of added contacts and has a button to create a new contact (New Contact View - NCV). The NVC view has a save button, and I use this button for two proposes:

  1. add the new contact to the list of contacts, this is happen is VM
  2. send a event to code-behind file off the view to goback to the main view.

It works! And with this, I avoid the VM to have to send a event message to the View.

But it is this wrong?

If is it wrong, there is a simple way to avoid this?

There is the magic line:

<Button Content="Save" Command="{Binding AddNewContactCommand}" Click="Button_Click" />
Sheridan
  • 68,826
  • 24
  • 143
  • 183
  • No, it is not. This is not MVVM any more, in fact it's worse than skipping MVVM altogether – Sten Petrov Apr 09 '15 at 23:29
  • Depending on your MVVM Framework, you could use a navigation manager/service to get to the previous page, which you inject into your ViewModel. Be careful to only inject the interface and not the concrete implementation of the navigation servers. Later one breaks MVVM pattern – Tseng Apr 10 '15 at 00:36
  • You could navigate in the AddCommand of the VM itself to adhere MVVM – bit Apr 10 '15 at 04:08
  • In general, yes, this is fine. The VM should handle all data related actions, and the view’s code-behind can be used for everything that only affects the view itself. So if there’s a button that affects both, then doing this sounds good to me. However, I would argue that changing the active view is *not* an action that should be handled in the code-behind but rather by the view model, or some parent view model that handles the navigation. – poke Apr 10 '15 at 08:01
  • The answer to this is highly dependent on how you normally navigate between your pages. If you always do it in codebehind then that's a problem. It's not difficult to implement VM based navigation, but if you've built a lot of infrastructure around codebehind navigation then it could present some challenges. – goobering Apr 10 '15 at 08:03

1 Answers1

0

Your question is opinion based and so you may get wildly varying answers. Your comments say "No, don't do that because you'll break the MVVM pattern", but that depends on the size and longevity and professionalism of your project and your programming style in general. In fact, using the code behind for view related logic is perfectly fine in MVVM, although I'm sure some die hard MVVM developers will disagree with this statement.

However, if you'd prefer to not use the code behind, there are other ways to load views from the view model and you can find a common one explained in the WPF MVVM navigate views question. There's too much there to show here, but the general idea is this:

All of your view models should extend an abstract base class, let's call it BaseViewModel:

public BaseViewModel ViewModel { get; set; }

In App.xaml, you could declare some simple DataTemplates to connect the views with the view models:

<DataTemplate DataType="{x:Type ViewModels:MainViewModel}">
    <Views:MainView />
</DataTemplate>
<DataTemplate DataType="{x:Type ViewModels:PersonViewModel}">
    <Views:PersonView />
</DataTemplate>
<DataTemplate DataType="{x:Type ViewModels:CompanyViewModel}">
    <Views:CompanyView />
</DataTemplate>

Now, wherever you use one of your BaseViewModel instances in your application, these DataTemplates will tell the framework to display the related view instead. You can display them like this:

<ContentControl Content="{Binding ViewModel}" />

To switch to a new view, you just need to set the ViewModel property from the MainViewModel class:

ViewModel = new PersonViewModel();

Please refer to the linked question for further information on this method.

Of course, once you have implemented this system, you'll probably be thinking 'How can I change the view model in the main view model from a child view model?' The answer to that can be found in the How to call functions in a main view model from other view models? question.

Community
  • 1
  • 1
Sheridan
  • 68,826
  • 24
  • 143
  • 183