0
votes

I am using Prism. I have a view(DetailMainUC.xaml) which hold many other views in the following way.

    <UserControl.Resources>
    <DataTemplate x:Key="View1Template" DataType="{x:Type vm:DetailMainUCViewModel}">
        <local:HomeUC />
    </DataTemplate>
    <DataTemplate x:Key="View2Template" DataType="{x:Type vm:DetailMainUCViewModel}">
        <local:WalkAwayBehaviorUC />
    </DataTemplate>
    <DataTemplate x:Key="View3Template" DataType="{x:Type vm:DetailMainUCViewModel}">
        <local:WakeUpOnApproachUC />
    </DataTemplate>
    <DataTemplate x:Key="View4Template" DataType="{x:Type vm:DetailMainUCViewModel}">
        <local:NoLockOnPresenceUC />
    </DataTemplate>
    <DataTemplate x:Key="View5Template" DataType="{x:Type vm:DetailMainUCViewModel}">
        <local:PeekDimmingUC />
    </DataTemplate>
    <DataTemplate x:Key="View6Template" DataType="{x:Type vm:DetailMainUCViewModel}">
        <local:SettingsUC />
    </DataTemplate>
</UserControl.Resources>
<Grid>
    <ContentControl Grid.Column="1" Grid.Row="1" Content="{Binding }">
        <ContentControl.Style>
            <Style TargetType="{x:Type ContentControl}">
                <Style.Triggers>
                    <DataTrigger Binding="{Binding SwitchView}" Value="Home">
                        <Setter Property="ContentTemplate" Value="{StaticResource View1Template}" />
                    </DataTrigger>
                    <DataTrigger Binding="{Binding SwitchView}" Value="Walk Away Behaviour">
                        <Setter Property="ContentTemplate" Value="{StaticResource View2Template}"></Setter>
                    </DataTrigger>
                    <DataTrigger Binding="{Binding SwitchView}" Value="Wake up on approach">
                        <Setter Property="ContentTemplate" Value="{StaticResource View3Template}" />
                    </DataTrigger>
                    <DataTrigger Binding="{Binding SwitchView}" Value="No lock on presence">
                        <Setter Property="ContentTemplate" Value="{StaticResource View4Template}" />
                    </DataTrigger>
                    <DataTrigger Binding="{Binding SwitchView}" Value="Peeking and Dimming">
                        <Setter Property="ContentTemplate" Value="{StaticResource View5Template}" />
                    </DataTrigger>
                    <DataTrigger Binding="{Binding SwitchView}" Value="Settings">
                        <Setter Property="ContentTemplate" Value="{StaticResource View6Template}" />
                    </DataTrigger>
                </Style.Triggers>
            </Style>
        </ContentControl.Style>
    </ContentControl>
</Grid>

Now I am using event aggregator to communicate between different view models in other regions. My view model for the above usercontrol is as follows:

public DetailMainUCViewModel(IEventAggregator eventAggregator, HomeViewModel homeViewModel)
{
    this.HomeVM = homeViewModel;
    this._eventAggregator = eventAggregator;
    HomeVM.Initialization(this._eventAggregator);
    this._eventAggregator.GetEvent<MenuClickEvent>().Subscribe(GetMenuName);
    SwitchView = "Home";

}

Now the property HomeVM is of type HomeViewModel which is view model of child DetailMainUCViewModel. Like this there are many other child view models are there. Now my problem is I am seeing constructor of HomeViewModel is getting called twice and same is happening for all other child view models. the main problem I am facing is while child view models are getting called second times , the eventAggregator is becoming null.

DetailsMainUCViewModel is parent viewmodel and HomeViewModel is child viewmodel. DetailMainUC.xaml holds the HomeUC.xaml in the way as mentioned in code section. I have written the below mentioned code too

<UserControl.DataContext>
    <vm:HomeViewModel></vm:HomeViewModel>
</UserControl.DataContext>

I suspect as I am using two places to attach datacontext so my viewmodel is getting called two times. in 1.HomeUC.xaml

2.Parent usercontrol DetailMainUC.xaml

But I am unable to remove them as it is needed. My class design is DetailMainUCViewModel is parent viewmodel and HomeViewModel is child viewmodel. DetailMainUC.xaml is parent view and HomeUC.xaml is child view. at the beginning the code snippet which I have given is from DetailMainUC.xaml (which holds all child usercontrols)

apart from this I am initializing my DetailMainUC.xaml in module where I have implemented IModule interface.

public class STDetailOptionsModule : IModule
{
    private readonly IRegionManager _regionManager;
    public STDetailOptionsModule(IRegionManager regionManager)
    {
        this._regionManager = regionManager;
    }

    public void OnInitialized(IContainerProvider containerProvider)
    {
        _regionManager.RegisterViewWithRegion(RegionNames.DetailOptionsRegion, typeof(DetailMainUC));
    }

    public void RegisterTypes(IContainerRegistry containerRegistry)
    {

    }
}

regards

1
Isn't this duplicate of a recently deleted question?Haukinger
@Haukinger you are right this is duplicate of recently deleted question. I did not found answer so I have put this question again. Is it wrong ? I do not know why some moderators deleted my question . Is my question inappropriate ? Still I could not understand that how could a question be deleted if it is valid question ?Payel

1 Answers

0
votes

If I have understood your question properly then I can say that you are using multiple usercontrols in same usercontrol to navigate by virtue of triggers.

This approach is not correct. Basically you want a navigation between various usercontorls.

Let me explain how to do this in Prism.

this.regionManager.RequestNavigate("your region name where the usercontrol will be put ",
                        navigationPath, NavigationCompleted);

NavigationCompleted is a call back method: navigationPath: is the usercontrol path which you want to place in a specified region.

Hope it is clear

As you said you are new to prism so let me explain vividly.

As I can see you have Views (WalkAwayBehaviorUC, WakeUpOnApproachUC, NoLockOnPresenceUC,PeekDimmingUC, SettingsUC). Now let me consider these views are in different projects or in same project but you want them to be displayed in your region that is RegionNames.DetailOptionsRegion.

Now to do that , you have to put all navigation logic in a centralized location. the best centralized location could be shell . So ShellViewModel.cs is the class where you have to write navigation logic.

So create a method like this :

private void NavigationInitialized(string navigationPath)
    {
        if (string.IsNullOrEmpty(navigationPath))
        {
            throw new Exception();//or send proper message to UI
        }

        this.regionManager.RequestNavigate(RegionNames.DetailOptionsRegion,
                    navigationPath, NavigationCompleted);

    } 

private void NavigationCompleted(NavigationResult  navigationResult)
    {

    }

Now the question is how to get this navigation name in ShellViewModel.cs. The solution is EventAggregator.

In the place where you want the usercontrol should navigate write.

this.eventAggregator.GetEvent<Navigated>().Publish("WalkAwayBehaviorUC");

now the Navigated event class should be like :

public class Navigated : PubSubEvent<string>
{
}

Now you have to subscribe this Navigated Event in ShellViewModel.cs

So in constructor of ShellViewModel.cs you have to write:

this.eventAggregator.GetEvent<Navigated>().Subscribe(NavigationInitialized);