Search code examples
c#wpfnavigationprism-7

How to navigate between View with Prism 7.2?


I'm writing an application and I want to put navigation in it. This application is using WPF and I'm using Prism 7.2.0.1367.

So I created 2 views: a HomePage and a ModeFileAttente view.

I'm also using the MVVM pattern.

Here is my app.xaml.cs :

public partial class App : PrismApplication
{
    protected override Window CreateShell()
    {
        return Container.Resolve<V.HomePage>();
    }

    protected override void RegisterTypes(IContainerRegistry containerRegistry)
    { 
        containerRegistry.RegisterDialog<V.HomePage, VM.HomePageViewModel>();
        containerRegistry.RegisterDialog<V.ModeFileAttente, VM.ModeFIleAttenteViewModel>();
    }

    protected override void ConfigureModuleCatalog(IModuleCatalog  moduleCatalog)
    {
        moduleCatalog.AddModule<Bootstrapper>();
    }
}

My HomePage.xaml:

<Window x:Class="TestWPF.View.HomePage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:prism="http://prismlibrary.com/"
    prism:ViewModelLocator.AutoWireViewModel="True"
    mc:Ignorable="d"
    Title="HomePage" Height="347.667" Width="664">
<Grid>
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="277*"/>
        <ColumnDefinition Width="16*"/>
    </Grid.ColumnDefinitions>

    <DockPanel Grid.ColumnSpan="2" Margin="0,0,0.333,-0.333">
        <Button Padding="0" DockPanel.Dock="Left" Content="Mode normal" Command="{Binding ClickCommand}" CommandParameter="ModeFileAttente"/>
        <Button Padding="0" DockPanel.Dock="Right" Content="Mode tournois" HorizontalAlignment="Stretch"/>
    </DockPanel>
    <ContentControl prism:RegionManager.RegionName="ContentRegion" Margin="5"  />
  </Grid>
</Window>

And this is the view model:

class HomePageViewModel : BindableBase, IDialogAware, INotifyPropertyChanged
{   

    #region Private region
    private readonly IRegionManager _regionManager;

    public event Action<IDialogResult> RequestClose;
    #endregion

    public DelegateCommand<string> ClickCommand { get; private set; }



    public string Title => throw new NotImplementedException();

    public HomePageViewModel(IRegionManager regionManager)
    {
        _regionManager = regionManager;
        ClickCommand = new DelegateCommand<string>(ExecuteClickCommand);
    }

    private void ExecuteClickCommand(string path) {
        _regionManager.RequestNavigate("ContentRegion", "FileAttente");
    }

    public bool CanCloseDialog()
    {
        throw new NotImplementedException();
    }

    public void OnDialogClosed()
    {
        throw new NotImplementedException();
    }

    public void OnDialogOpened(IDialogParameters parameters)
    {
        throw new NotImplementedException();
    }
}

I also got a Bootstrapper class :

public class Bootstrapper : IModule
{
    public void OnInitialized(IContainerProvider containerProvider)
    {
    }

    public void RegisterTypes(IContainerRegistry containerRegistry)
    {
        containerRegistry.RegisterForNavigation<ModeFileAttente>();
    }
}

My MVVM pattern work's well, but when I want to navigate between my "HomePage" and my "ModeFileAttente" view, nothing happens except a "System.Object" on my view.

I already search what could be the problem, but I didn't something that resolve my issue.

Did someone still got this error with this version of prism ?

PS: my 2 view are in a "View" folder, same for the view model in a ViewModel folder


Solution

  • I believe you should register view with region on initialize. try the below code

    public class Bootstrapper : IModule
    {
         public void OnInitialized(IContainerProvider containerProvider)
         {
            _regionManager.RegisterViewWithRegion("RegionName", typeof(View));
            _regionManager.RegisterViewWithRegion("RegionName", typeof(View2));
         }
    }
    

    Now you can use

    _regionManager.RequestNavigate("RegionName", "View"); 
    

    Or

    _regionManager.RequestNavigate("RegionName", "View2"); 
    

    Update

    If we use prism then there should be a dependency injection framework associated to it for example MEF or Unityfor my project I am using Prism.Unity.Wpf if you are using Unity then you can ask your dependency injector to inject RegionManager by adding a constructor which will be injected by a IRegionManager see below

        readonly IRegionManager _regionManager;
        public Bootstrapper(IRegionManager regionManager)
        {
            _regionManager = regionManager;
        }
    

    When you Inject IRegionManager to the constructor Unity know to provide same instance all the time as it is maintained in Unity so no need to worry about using the same instance of IRegionManager elsewhere.

    when we use prism:RegionManager.RegionName="ContentRegion" in XAML we are actually keeping a place holder to say Prism that there is a region which will be filled by any VIEW at some point look for it.

    This is my understanding. Let me know if you find this useful Thanks.