#c# #wpf #mvvm #navigation #prism
Вопрос:
В моем проекте я использую Prism для представлений и ViewModels. Теперь я хочу загрузить другое представление в UserControl в MainWindowView. Я читал, что могу сделать это с помощью этого:
_regionManager.RegisterViewWithRegion("MainRegion", typeof(View));
Но, к сожалению, я понятия не имею, как добраться до экземпляра IRegionManger
в моей ViewModel. Во всех примерах, которые я нашел, используются другие переменные, но не показано, откуда они берутся.
Это мое мнение:
<Window x:Class="PortfolioVisualizer.MainWindow"
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:local="clr-namespace:PortfolioVisualizer"
mc:Ignorable="d"
xmlns:prism="http://prismlibrary.com/"
prism:ViewModelLocator.AutoWireViewModel="True"
Title="MainWindow" Height="450" Width="800">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="1*"/>
<ColumnDefinition Width="15*"/>
</Grid.ColumnDefinitions>
<StackPanel Grid.Column="0">
<Button Command="{Binding NavigateCommand}" CommandParameter="AddAssetView">
<StackPanel>
<Image/>
<Label Content="Add Asset"/>
</StackPanel>
</Button>
<Button Command="{Binding NavigateCommand}" CommandParameter="ConfigView">
<StackPanel>
<Image/>
<Label Content="Settings"/>
</StackPanel>
</Button>
</StackPanel>
<Grid Grid.Column="1">
<ContentControl prism:RegionManager.RegionName="MainRegion"/>
</Grid>
</Grid>
</Window>
Это моя модель просмотра:
public class MainWindowViewModel : ViewModelBase
{
private readonly IRegionManager _RegionManager;
public DelegateCommand<string> NavigateCommand;
public MainWindowViewModel(IRegionManager regionManager)
{
_RegionManager = regionManager;
NavigateCommand = new DelegateCommand<string>(ExecuteNavigateCommand);
_RegionManager.RegisterViewWithRegion("MainRegion", typeof(DashboardView));
}
private void ExecuteNavigateCommand(string viewName)
{
if (string.IsNullOrWhiteSpace(viewName))
return;
_RegionManager.RequestNavigate("ContentRegion", viewName);
}
}
Это ViewModdelBase
public class ViewModelBase : BindableBase
{
public ViewModelBase()
{
}
}
(Я знаю, что ViewModelBase просто лишний, но есть кое-что, что придет позже)
Ответ №1:
У вас есть контейнер, который вводит региональный менеджер, как и любую другую зависимость:
internal class MyViewModel
{
public MyViewModel( IRegionManager regionManager )
{
regionManager.DoSomeStuff(); // or just put it into a field for later use
}
}
Обратите внимание, что это работает только автоматически, если вы не new
выполняете модель представления вручную ни в коде, ни в xaml. Вместо этого создайте его с помощью фабрики, которая сама вводится (например Func<MyViewModel> myViewModelFactory
), если вы сначала просматриваете модель (рекомендуется в большинстве случаев), или используйте Prism ViewModelLocator
, чтобы создать ее как контекст данных, если вы сначала просматриваете.
Комментарии:
1.
ViewModelLocator.AutoWireViewModel=true
достаточно @arne — учитывая, что ваши представления находятся вViews
пространстве имен и моделях представленийViewModels
, и у них есть общее базовое имя, напримерMySpecialView
, иMySpecialViewModel
. Вы также можете зарегистрировать пары view / view model у поставщика view model, если вам не нравится конвенционный подход (хотя это совершенно нормально).2. Как вы создаете модель представления? Локатор модели представления будет использовать контейнер и предоставлять все параметры. Если вы вручную вызываете свой конструктор, вы должны предоставить их самостоятельно.
3. @arne опубликованный вами xaml — это только открывающий тег — мы не видим
<Window.DataContext>
, например, есть ли там.<viewModels:MainWindowViewModel/>
это тоже вызов конструктора. Также обратите внимание, что представления должны находиться вViews
пространстве имен и просматривать модели,ViewModels
чтобы работало соглашение по умолчанию.4. Вы создаете
MainWindow
сResolve<MainWindow>()
помощью ? Тогда это должно работать сPrismApplication
s по умолчанию.ConfigureViewModelLocator
Вызывается в вашей настройке, т.Е. Достигнута ли там точка останова?5. Если
ConfigureViewModelLocator
не вызывается, и вы не устанавливаете фабрику модели представления вручную, Prism используетActivator.CreateInstance
по умолчанию, что не может ничего вводить и объясняет исключение, которое вы наблюдаете. Смотрите код здесь . Какой контейнер, приложение prism, загрузчик и т. Д. используете ли вы?