WPF navigation using MVVM

2019-09-12 12:21发布

问题:

I want to know some things regarding navigation using MVVM.

Q1: Clicking in the Login Button if the authentication is ok, I want to open a completely new window, how I can do this without loosing the MVVM pattern. (I know the simple approach NewWindow w = new NewWindow(), show & hide and its ok) but this is so terrible that I have nightmares thinking about it. How can I do it?

Q2: The recovery button I want to completely reshape the login page, two have new text boxes and two buttons (submit recovery and cancel) using cancel I want to show the login again. How can I do it?

What I know: having two buttons in the same MainView and loading different views but the buttons have to stay there like a web page (this is a desktop app in the first iteration, will evolve to mobile as well).

Best regards,

回答1:

WPF/XAML is an extraordinary technology, there are many ways to do the same thing and even the simplest of explanations is too complicated to deliver on a forum like SO. To fully understand WPF, MVVM and XAML you need to look at example code and lots of it, you need to pick it apart and see how its working then modify it to do something else, strip parts out to implement in your own code and follow tutorials. Only by doing that 24/7/52 can you expect to become familiar with it.....

I'm not going to post any code here coz there is just too much. So here is a download to just about the simplest example I could come up with

http://www.mediafire.com/download/3bubiq7s6xw7i73/Navigation1.rar

the example is a modification of Rachel Lim example. It simply contains Views and ViewModels, there are no Models or data. It demonstrates switching between two different Views. Download and un-RAR it (with win RAR) You will need to step though the code, figure out what its doing and how its doing it then modify it to suit your needs... Or modify your needs to suit the code.....

Maybe as your first task, Using my example code from the download link, you should try to add a third view plus code\Button to switch between three views....

Good luck



回答2:

For the first question, you have to ask yourself who is responsible for opening a new Window. One might say that the UI is responsible for opening a new Window, regardless of the data in the ViewModel, therefore there is no problem in a button opening a new Window(), as there is no data actually involved. Do you need to open or close a window by manipulating an IsClose data item? I mean, really, do you find any useful scenario where you might need that? Then the ViewModel would be involved.

For the second question, you press some buttons and then some part of the UI changes. You have to ask yourself if any important part of the ViewModel changes when you do that, or is it just a case of having some IsOpen or IsShown variable that shows or hides some controls that are already connected to the underlying ViewModel.

There is no one-to-one relationship between Views and ViewModels. You may have many to many or you can have one huge ViewModel connecting to all Views. The point of MVVM is not to make the UI behave in a certain way, but to govern the logic of the application. The UI should then mould itself on that.



回答3:

It is appropriate to use DataTemplates if you want to dynamically switch Views depending on the ViewModel:

<Window>
   <Window.Resources>
      <DataTemplate DataType="{x:Type ViewModelA}">
         <localControls:ViewAUserControl/>
      </DataTemplate>
      <DataTemplate DataType="{x:Type ViewModelB}">
         <localControls:ViewBUserControl/>
      </DataTemplate>
   <Window.Resources>
  <ContentPresenter Content="{Binding CurrentView}"/>
</Window>

If Window.DataContext is an instance of ViewModelA, then ViewA will be displayed and Window.DataContext is an instance of ViewModelB, then ViewB will be displayed.

Let me show an example where it can be seen where you should put DataTemplates:

<Window x:Class="SimpleMVVMExample.ApplicationView"
        ...The code omitted for the brevity...
        Title="Simple MVVM Example with Navigation" Height="350" Width="525">
    <Window.Resources>
       <DataTemplate DataType="{x:Type ViewModelA}">
         <localControls:ViewAUserControl/>
      </DataTemplate>
      <DataTemplate DataType="{x:Type ViewModelB}">
         <localControls:ViewBUserControl/>
      </DataTemplate>
    </Window.Resources>

    <DockPanel>
        <Border DockPanel.Dock="Left" BorderBrush="Black" BorderThickness="0,0,1,0">
            <ItemsControl ItemsSource="{Binding ListOfViewModels}">
                <ItemsControl.ItemTemplate>
                    <DataTemplate>
                        <Button Content="{Binding Name}"
                                Command="{Binding DataContext.ChangePageCommand, RelativeSource={RelativeSource AncestorType={x:Type Window}}}"
                                CommandParameter="{Binding }"
                                Margin="2,5"/>
                    </DataTemplate>
                </ItemsControl.ItemTemplate>
            </ItemsControl>
        </Border>

        <ContentControl Content="{Binding CurrentDataTemplateViewModel}" />
    </DockPanel>
</Window>

And I highly recommend you pay attention to Prism framework. This tutorial is very nice.