0
votes

i'm currently developing an application using C# WPF + PRISM 6.0. Right now i want to implement a data import assistant as a modal dialog. This dialog has to be navigable, so i have defined a region within it, where the assistant pages are going to be shown after the user clicks "next" or "previous".

The modal dialog will be displayed by using an IDialogService.

My problem is, that the modal dialog region is not resolved, hence i can't add the assistant views to it. Here is what i'm trying

within my Module i'm registering the application views and viewmodels and try to add the views to the regions

Container.RegisterType<IAppView, AppView>();
Container.RegisterType<IAppViewModel, AppViewModel>();

IViewModel viewModel = Container.Resolve<IViewModel>();
var region = RegionManager.Regions.FirstOrDefault(r => r.Name == "MainAppRegion");
if (region != null)
{
    region.Add(viewModel.View);
}

Container.RegisterType<IModalDialogView, ModalDialogView>();
Container.RegisterType<IModalDialogViewModel, ModalDialogViewModel>();

# here the region is null, and i can't add the ModalDialogView to it
IViewModel viewModel = Container.Resolve<IModalDialogViewModel>();
region = RegionManager.Regions.FirstOrDefault(r => r.Name == "ModalDialogCenterRegion");
if (region != null)
{
    region.Add(viewModel.View);
}

The modal dialog is a Window, because the IDialogService requires a window.

Is this the correct approach to implement such an assistant?

Thanks and Regards,

Michael

1
What the heck is viewModel.View supposed to do? Besides, I think your region is not registered with the region manager, given it's in a popup window. Have a look here: stackoverflow.com/questions/41212881/… - Haukinger
I edited the code snippet. now the container registers my views and viewmodels just as it is in my real code. That was a type on my side. I use the resolved viewModel.View property to add the view to the region. That is a pattern i have from Brian Lagunas - Michael
What's wrong with RegionManager.RequestNavigate? Navigate to either the view or the view model and prism or wpf will create the other. - Haukinger
when i use RegionManager.RequestNavigate, the Region is not automatically added to the RegionManager's Regions. When i try then to add views to the region the region manager fails to resolve this region. I get the Exception: This RegionManager does not contain a Region with the name 'ModalDialogCenterRegion' - Michael
That's what's written in the linked answer - you have to add the region to the region manager manually if the control hosting the region is not part of the visual tree initially - Haukinger

1 Answers

1
votes

Here the source for my IModalDialogView (ImportDialogView) and IModalDialogViewModel (ImportDialogViewModel)

The interface definition below is a bit of a construction site. I derive from two interfaces (IModalDialogViewModel and IInteractionRequestAware), because i am not sure which pattern for modal dialogs i will use or which pattern is better for my needs. So far deriving from both, does not break functionality.

IImportDialogViewModel.cs

using System.Collections.Generic;
using Infrastructure.Interfaces;
using Model;
using MvvmDialogs;
using Prism.Interactivity.InteractionRequest;
using Prism.Regions;

namespace Modules.Interfaces.ImportAssistant
{
    public interface IImportDialogViewModel : IViewModel, IModalDialogViewModel, IInteractionRequestAware
    {
        IEnumerable<Data> ImportedData { get; set; }
        IRegionManager RegionManager { get; set; }
    }
}

importdialogview.xaml

<UserControl x:Class="Modules.View.ImportAssistant.ImportDialogView" 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:inf="clr-namespace:Infrastructure;assembly=Infrastructure" xmlns:local="clr-namespace:Modules.View.ImportAssistant"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:md="https://github.com/fantasticfiasco/mvvm-dialogs"
             xmlns:prism="http://prismlibrary.com/" xmlns:ImportAssistant="clr-namespace:Modules.ViewModel.ImportAssistant"
             Width="1200" Height="600"
             mc:Ignorable="d" Loaded="ImportDialogView_OnLoaded"
             d:DataContext="{d:DesignInstance d:Type=ImportAssistant:ImportDialogViewModel}"
             md:DialogServiceViews.IsRegistered="True">
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="80" />
            <RowDefinition Height="*" />
            <RowDefinition Height="40" />
        </Grid.RowDefinitions>
        <Label Grid.Row="0"
               Content="{Binding Title, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
               FontSize="24"
               Style="{StaticResource TitleLabelStyle}" />
        <ContentControl x:Name="AssistantDialogContentControl" Grid.Row="1"
                        prism:RegionManager.RegionName="{x:Static inf:RegionNames.ImportAssistantMain}" />
        <Grid Grid.Row="2">
            <Grid.ColumnDefinitions>
                <ColumnDefinition />
                <ColumnDefinition />
            </Grid.ColumnDefinitions>
            <StackPanel Grid.Column="0" HorizontalAlignment="Left"
                        Orientation="Vertical">
                <Button Command="{Binding AbortAssistantCommand}"
                        Content="Abort"
                        Style="{StaticResource DefaultDialogButton}" />
            </StackPanel>
            <StackPanel Grid.Column="1" HorizontalAlignment="Right"
                        Orientation="Horizontal">
                <Button Command="{Binding PreviousCommand}"
                        Content="Previous"
                        Style="{StaticResource DefaultDialogButton}" />
                <Button Command="{Binding NextCommand}"
                        Content="Next"
                        Style="{StaticResource DefaultDialogButton}" />
                <Button Command="{Binding FinishCommand}"
                        Content="Finish"
                        Style="{StaticResource DefaultDialogButton}" />
            </StackPanel>
        </Grid>
    </Grid>
</UserControl>

Importdialogview.xaml.cs

using System.Windows;
using System.Windows.Controls;
using Infrastructure.Interfaces;
using Modules.Interfaces.ImportAssistant;
using Prism.Regions;
using Infrastructure;
using Microsoft.Practices.ServiceLocation;
using System.Linq;

namespace Modules.View.ImportAssistant
{
    /// <summary>
    /// Interaction logic for ImportDialogView.xaml
    /// </summary>
    public partial class ImportDialogView : UserControl, IImportDialogView
    {
        public ImportDialogView(IImportDialogViewModel viewModel)
        {
            InitializeComponent();

            ViewModel = viewModel;
            viewModel.View = this;

            var regionManager = ServiceLocator.Current.GetInstance<IRegionManager>();

            if (regionManager.Regions.Any(r => r.Name == RegionNames.ImportAssistantMain) == false)
            {
                RegionManager.SetRegionName(AssistantDialogContentControl, RegionNames.ImportAssistantMain);
                RegionManager.SetRegionManager(AssistantDialogContentControl, regionManager);
            }
        }

        public IViewModel ViewModel
        {
            get { return (IImportDialogViewModel)DataContext; }
            set { DataContext = value; }
        }

        private void ImportDialogView_OnLoaded(object sender, RoutedEventArgs e)
        {

        }
    }
}

importdialogviewmodel.cs

using Model;
using Modules.View.ImportAssistant;
using Prism.Commands;
using Prism.Mvvm;
using Prism.Regions;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows.Input;
using Infrastructure.Interfaces;
using Modules.Interfaces.ImportAssistant;
using Infrastructure;
using Prism.Interactivity.InteractionRequest;

namespace Modules.ViewModel.ImportAssistant
{
    public class ImportDialogViewModel : BindableBase, IImportDialogViewModel
    {
        public IRegionManager RegionManager { get; set; }

        private string _title;
        public string Title
        {
            get { return _title; }
            set
            {
                SetProperty(ref _title, value, nameof(Title));
            }
        }
        public IView View { get; set; }

        public IEnumerable<Data> ImportedData { get; set; }



        private INotification _notification;
        public INotification Notification
        {
            get { return _notification; }
            set
            {
                var confirmation = value as ImportConfirmation;
                if (confirmation != null)
                {
                    //SetProperty(ref _notification, value, nameof(Notification));
                    _notification = confirmation;
                    RaisePropertyChanged(nameof(Notification));
                }
            }
        }


        public Action FinishInteraction { get; set; }


        private bool? _dialogResult;
        public bool? DialogResult
        {
            get { return _dialogResult; }
            set
            {
                if (_dialogResult != value)
                {
                    SetProperty(ref _dialogResult, value, nameof(DialogResult));
                }
            }
        }


        public ICommand AbortAssistantCommand { get; set; }
        public ICommand NextCommand { get; set; }
        public ICommand PreviousCommand { get; set; }
        public ICommand FinishCommand { get; set; }

        public ImportDialogViewModel(IImportDialogView view, IRegionManager r)
        {
            RegionManager = r;

            View = view;
            View.ViewModel = this;

            InitializeCommands();
        }

        private void InitializeCommands()
        {
            AbortAssistantCommand = new DelegateCommand(() => { DialogResult = false; });

            NextCommand = new DelegateCommand(() =>
            {
                var importDialogMainRegion = RegionManager.Regions.FirstOrDefault(r => r.Name == RegionNames.ImportAssistantMain);
                if (importDialogMainRegion != null)
                {
                    var firstActiveView = importDialogMainRegion.ActiveViews.FirstOrDefault();
                    string viewType = null;
                    if (firstActiveView is IImportStartView)
                    {
                        viewType = typeof(FileSelectionView).FullName;
                    }
                    else if (firstActiveView is FileSelectionView)
                    {
                        viewType = typeof(DataSelectionView).FullName;
                    }


                    if (string.IsNullOrEmpty(viewType) == false)
                    {
                        RegionManager?.RequestNavigate(RegionNames.ImportAssistantMain, viewType); 
                    }
                }
            });

            PreviousCommand = new DelegateCommand(() =>
            {
                var importDialogMainRegion = RegionManager.Regions.FirstOrDefault(r => r.Name == RegionNames.ImportAssistantMain);
                if (importDialogMainRegion != null)
                {
                    var firstActiveView = importDialogMainRegion.ActiveViews.FirstOrDefault();

                }
            });

            FinishCommand = new DelegateCommand(() => 
            {
                DialogResult = true;
                FinishInteraction?.Invoke();
            });
        }


    }
}