Prism: навигация между различными пользовательскими элементами управления - PullRequest
0 голосов
/ 31 марта 2020

Я использую Prism. У меня есть представление (DetailMainU C .xaml), которое содержит множество других представлений следующим образом.

    <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>

Теперь я использую агрегатор событий для связи между различными моделями представлений в других регионах. Моя модель представления для вышеуказанного usercontrol выглядит следующим образом:

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

}

Теперь свойство HomeVM имеет тип HomeViewModel, который является моделью представления дочернего DetailMainUCViewModel. Подобно этому, есть много других моделей детского представления. Теперь моя проблема в том, что я вижу, что конструктор HomeViewModel вызывается дважды, и то же самое происходит для всех других моделей дочерних представлений. Основная проблема, с которой я сталкиваюсь, заключается в том, что пока модели дочерних представлений вызывают второй раз, eventAggregator становится нулевым.

DetailsMainUCViewModel является родительской моделью представления, а HomeViewModel является дочерней моделью представления. DetailMainU C .xaml содержит HomeU C .xaml так, как указано в разделе кода. Я также написал приведенный ниже код:

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

Я подозреваю, что я использую два места для присоединения текста данных, поэтому моя модель представления вызывается два раза. в 1.HomeU C .xaml

2. Родительский пользовательский контроль DetailMainU C .xaml

Но я не могу удалить их по мере необходимости. Мой дизайн класса - DetailMainUCViewModel - родительская viewmodel, а HomeViewModel - дочерняя viewmodel. DetailMainU C .xaml - это родительское представление, а HomeU C .xaml - это дочернее представление. вначале приведенный фрагмент кода взят из DetailMainU C .xaml (который содержит все дочерние элементы управления пользователя)

, кроме этого, я инициализирую свой DetailMainU C .xaml в модуле, в котором я реализовал Интерфейс IModule.

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 Ответ

0 голосов
/ 31 марта 2020

Если я правильно понял ваш вопрос, то могу сказать, что вы используете несколько пользовательских элементов управления в одном пользовательском элементе управления для навигации с помощью триггеров.

Этот подход не верен. В основном вам нужна навигация между различными usercontorls.

Позвольте мне объяснить, как это сделать в Prism.

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

NavigationCompleted - это метод обратного вызова: navigationPath: это путь к пользовательскому контролю, который вы хотите разместить в указанном регионе.

Надеюсь, что это понятно

Как вы сказали, вы новичок в призме, поэтому позвольте мне объяснить это ярко.

Как я вижу, у вас есть Просмотры (WalkAwayBehaviorU C, WakeUpOnApproachU C, NoLockOnPresenceU C, PeekDimmingU C, Настройки U C). Теперь позвольте мне рассмотреть эти представления в разных проектах или в одном и том же проекте, но вы хотите, чтобы они отображались в вашем регионе RegionNames.DetailOptionsRegion.

Теперь, чтобы сделать это, вы должны поместить все навигационные логи c в централизованное место. лучшее централизованное расположение может быть оболочкой. Итак, ShellViewModel.cs - это класс, в котором вы должны написать навигационную логику c.

Итак, создайте метод, подобный этому:

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)
    {

    }

Теперь вопрос в том, как получить это имя навигации в ShellViewModel.cs. Решением является EventAggregator.

В том месте, где вы хотите, чтобы usercontrol должен был перемещаться по записи.

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

теперь класс перемещаемых событий должен выглядеть следующим образом:

public class Navigated : PubSubEvent<string>
{
}

Теперь вы должны подписаться на это Navigated Event в ShellViewModel.cs

Так что в конструкторе ShellViewModel.cs вы должны написать:

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