3

An example is switching the main view according to the selected item in a hamburger menu. Also sometimes it is just a small part of the GUI that changes according to the application state or according to user interaction with other parts of the GUI.

In WebForms days we used to create a tab control and hide the tab buttons bars and change the current tab page programmatically. Or stack the views on top of each other in design and in runtime hide all but one.

In WPF and MVVM I've seen people creating DataTemplate for each view, attach each to a view model and switch by changing the bound object to be of a different view model type and so the view changes.

I can see why that is a good idea for the hamburger menu views, but for some other cases, there are not necessarily a view model for each view. And in that case I'd like to escape having to create dummy view models for each view just to be able to switch between them rather than really having different types of data that I need to bind to each view.

Am I right to be concerned about this design detail?

Anyone had the same situation? What was the way you achieved the switch view effect?

In general, assuming there is no different type of data attached to each of the views to switch between, is it a correct practice to create view models just for something that is purely GUI? In other words, is view models more coupled to the data and what kind of data is available or to the GUI and the types of view we need to cover? And should we write the code for changing views on certain triggers in code behind in case we agreed that this is purely GUI and view models are not to be involved?

  • 2
    For detailed guidance on navigation techniques in WPF, have a look here: prismlibrary.readthedocs.io/en/latest/WPF/08-Navigation – Robert Harvey Nov 9 '17 at 4:11
  • 1
    I have done lots of MVVM, although not with WPF. Views don’t have to be bound to a view model, you can have a view for example that just shows your application logo. When I have an area that can display different data at different times I create a view for the outer container and have it subscribe to an event that causes it to replace the view that it contains. There must be a way to do this in WPF. BTW are you using Prism? – bikeman868 Nov 9 '17 at 5:59
  • 1
    One way to do it is to create a container control such as a Grid and then dynamically set some view as it's child (you can even do it through a binding). This could be the job of some other class that knows about the various views, so that the views themselves can remain decoupled. You can do this with all kinds of views - controls, custom views with or without view models, views that share the same view model, etc. – Filip Milovanović Nov 9 '17 at 8:45
  • 1
    I guess one of the benefits of MVVM is to be able to create unit tests for your user interfaces (by testing your view models). That said, I don't think would be a bad design to actually create different view models for different views, even if they internally represent the same data. This will allow you to test your interfaces, testing if these small views are actually reflecting what they should render to the user. IMO they're not dummy, and this is the benefit from MVVM. But, alternatively you could create different Templates and assign them in XAML with triggers. – Emerson Cardoso Nov 9 '17 at 11:10
  • 1
1

In MVVM, the ViewModel contains the state of your UI. The View is merely a reflection of that state. This reflection of state is accomplished via databinding, converters, styles, etc.

I think what you want is a state variable on your ViewModel and have visibility of various UI bits bound to that state.

First, define a state enum and create a property on your VM:

    enum ViewState
    {
        State1,
        State2
    }

    class MyVM
    {
        public ViewState ViewState {get;set;}
    }

Then in your view, you can hide/show UI elements using triggers:

    <StackPanel>
        <StackPanel.Style>
            <Style TargetType="StackPanel">
                <Setter Property="Visibility" Value="Collapsed" />
                <Style.Triggers>
                    <DataTrigger Binding="{Binding Path=ViewState}" Value="{x:Static local:ViewState.State1}">
                        <Setter Property="Visibility" Value="Visible" />
                    </DataTrigger>
                </Style.Triggers>
            </Style>
        </StackPanel.Style>
    </StackPanel>
| improve this answer | |
1

is it a correct practice to create view models just for something that is purely GUI?

Yes, it is correct, since the core purpose of having a ViewModel is to represent something in your UI. Plus, you can unit test these changes in the UI by testing changes in your view models.

should we write the code for changing views on certain triggers in code behind in case we agreed that this is purely GUI and view models are not to be involved?

If these are only pure GUI concerns, you could either write this trigger in code-behind, in XAML or make use of VisualStateManager. I think all of these options address your concern. But, you won't be able to unit test your GUI flow with these options IMO.

| improve this answer | |
0

I’m approaching my first WPF project with the same question as the OP, and the more I think about it, the more my thinking is:

Your, say, CRUD actions, are all working with the same Model Obejct, and that object probably has a way of presenting itself (its own view model). So it’s tempting to think “I want to do MVVM right and these are all the same model and I’m just showing them differently, hence different views not different view models.

My first idea, as others have suggested, was representing the different scenarios as some kind of enum in the main ViewModel, and binding the choice of DataTemplate or ControlTemplate to that enum.

BUT, since a View model is an abstraction of how the model object is being presented, an abstraction of what you’re doing with it, then each action scenario (create, read, update, etc) is indeed a different thing you’re doing with the object, and would indeed be best represented by a separate view model.

| improve this answer | |

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.