Adrian
Adrian

Reputation: 395

WPF with multiple views plus Prism and Unity

I have to write an application in WPF C#. My problem is I don't know how to work with multiple views. Till know I know how use Prism to wire a ViewModel to View through bindings, at basic level. I have learnt a bit of Unity to register ViewModel to View in App.xml.cs, through overriding the OnStartup method and using of UnityContainer.

I want to know how to navigate from View 1 to View 2 and vice versa. I want to navigate through a button and the views are different.

Can you help me,please? Some advices?

Like this,decoherence! enter image description here

Upvotes: 0

Views: 1345

Answers (2)

user5420778
user5420778

Reputation:

It is extremely easy to do this with Prism Navigation, and it doesn't require you to create dependencies on ViewModels, or introduce performance lags with the use of dynamic DataTemplates. I suggest reading the documentation on Prism navigation.

https://github.com/PrismLibrary/Prism/blob/master/Documentation/WPF/60-Navigation.md#view-based-navigation

Essentially you use a combination of ReqestNavigate, GoBack, and GoForward.

There is also a sample available for you to study here:

https://github.com/PrismLibrary/Prism-Samples-Wpf/tree/master/View-Switching%20Navigation_Desktop

You should also watch this course that walks you through exactly what you are asking:

https://app.pluralsight.com/library/courses/prism-introduction/table-of-contents

Upvotes: 0

Xi Sigma
Xi Sigma

Reputation: 2372

I have an example that i wrote long ago and it does not require any framework nonsense, based on my experience the WPF MVVM frameworks are useless for the most part and tend to complicate simple things all you need is an ICommand implementation and a ViewModelBase which implements INotiftyPropertyChanged, here is a simple illustration:

XML:

   <Window.Resources>
        <DataTemplate DataType="{x:Type local:ViewModel1}">
            <local:View1/>
        </DataTemplate>
        <DataTemplate DataType="{x:Type local:ViewModel2}">
            <local:View2/>
        </DataTemplate>
        <DataTemplate DataType="{x:Type local:ViewModel3}">
            <local:View3/>
        </DataTemplate>
    </Window.Resources>
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="*"></RowDefinition>
            <RowDefinition></RowDefinition>
        </Grid.RowDefinitions>
        <ContentControl Content="{Binding CurrentViewModel}">
        </ContentControl>

        <StackPanel Orientation="Horizontal" Grid.Row="1" VerticalAlignment="Bottom">
            <Button Command="{Binding PrevViewModel}">Previouws View</Button>
            <Button Command="{Binding NextViewModel}">Next View</Button>
            <Button Command="{Binding SwitchToViewModel}" CommandParameter="{x:Type local:ViewModel1}">Switch To View1</Button>
            <Button Command="{Binding SwitchToViewModel}" CommandParameter="{x:Type local:ViewModel2}">Switch To View2</Button>
            <Button Command="{Binding SwitchToViewModel}" CommandParameter="{x:Type local:ViewModel3}">Switch To View3</Button>
        </StackPanel>
    </Grid>

Given the above when ever the CurrentViewModel property changes, the View will get selected based on the DataTemplate resources, and the DataContext of the Window is set to the MainViewModel.

The main ViewModel looks like the following:

 public class MainViewModel : ViewModelBase
    {
        //add instances to all the ViewModels you want to switch between here, and add templates for them in your resources specifying the x:type and the view or data template to be used
        public ObservableCollection<ViewModelBase> ViewModels { get; set; } = new ObservableCollection<ViewModelBase>();

        private ViewModelBase _currentViewModel;

        public ViewModelBase CurrentViewModel {
            get { return _currentViewModel; }
            set { SetField(ref _currentViewModel, value); }
        }

        private ICommand _nextViewModel;
        public ICommand NextViewModel
        {
            get
            {
                return _nextViewModel = _nextViewModel ?? new RelayCommand(p =>
                  {
                      CurrentViewModel = ViewModels[ViewModels.IndexOf(CurrentViewModel) +1];
                  }, p =>
                  {
                      return ViewModels.IndexOf(CurrentViewModel) + 1 != ViewModels.Count && CurrentViewModel != null;
                  });
            }
        }

        public ICommand _prevViewModel;
        public ICommand PrevViewModel
        {
            get
            {
                return _prevViewModel = _prevViewModel ?? new RelayCommand(p =>
                {
                    CurrentViewModel = ViewModels[ViewModels.IndexOf(CurrentViewModel) - 1];
                }, p =>
                {
                    return ViewModels.IndexOf(CurrentViewModel) != 0 && CurrentViewModel!=null;
                });
            }
        }

        private ICommand _switchToViewModel;
        public ICommand SwitchToViewModel
        {
            get
            {
               return _switchToViewModel = _switchToViewModel ?? new RelayCommand(p =>
                {
                    CurrentViewModel = this.ViewModels.FirstOrDefault(vm=>vm.GetType()==p as Type);
                }, p =>
                {
                    return this.ViewModels.FirstOrDefault(vm => vm.GetType() != p as Type) != null;
                });
            }
        }
    } 

The result looks like

enter image description here

Upvotes: 2

Related Questions