I am trying to populate the ItemsSource
of a ComboBox
(a derivative of ItemsControl
) via a region.
View
The scoped RegionManager
(found on the View Model) is assigned to the view via prism:RegionManager.RegionManager="{Binding RegionManager}"
.
MainWindow.xaml
<Window x:Class="Applications.Testing.Wpf.RegionCreationTester.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:Applications.Testing.Wpf.RegionCreationTester"
xmlns:prism="http://www.codeplex.com/prism"
mc:Ignorable="d"
Title="MainWindow" Height="350" Width="525"
prism:RegionManager.RegionManager="{Binding RegionManager}"
prism:ViewModelLocator.AutoWireViewModel="True">
<Grid>
<ComboBox prism:RegionManager.RegionName="{x:Static local:RegionNames.itemsControlRegion}"/>
</Grid>
</Window>
MainWindow.xaml.cs
namespace Applications.Testing.Wpf.RegionCreationTester
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window, IModelled<MainWindowViewModel>
{
public MainWindowViewModel ViewModel
{
get
{
return (MainWindowViewModel)DataContext;
}
set
{
DataContext = value;
}
}
public MainWindow()
{
InitializeComponent();
ViewModel.PopulateItemsControl();
}
}
}
ViewModel
The view model is assigned to the view's DataContext via prism:ViewModelLocator.AutoWireViewModel="True"
.
MainWindowViewModel.cs
namespace Applications.Testing.Wpf.RegionCreationTester
{
public class MainWindowViewModel
{
/// <summary>
/// Gets the <see cref="RegionManager"/> scoped to this control.
/// </summary>
/// <remarks>Exists so that child controls can register regions for their own child controls which are also child controls in this control.</remarks>
public RegionManager RegionManager { get; } = new RegionManager();
/// <summary>
/// Adds some child views to the <see cref="RegionNames.itemsControlRegion"/>.
/// </summary>
/// <remarks>Normally these views would be resolved using an IoC container but this have been omitted for brevity.</remarks>
public void PopulateItemsControl()
{
var region = RegionManager.Regions[RegionNames.itemsControlRegion];
region.Add(new TextBlock { Text = "Item #1" });
region.Add(new Button { Content = "Item #2" });
}
}
}
RegionNames.cs
namespace Applications.Testing.Wpf.RegionCreationTester
{
public static class RegionNames
{
public const string itemsControlRegion = "collectionRegion";
}
}
Bootstrapper
App.xaml
<Application x:Class="Applications.Testing.Wpf.RegionCreationTester.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"/>
App.xaml.cs
namespace Applications.Testing.Wpf.RegionCreationTester
{
/// <summary>
/// Interaction logic for App.xaml
/// </summary>
public partial class App : Application
{
protected override void OnStartup(StartupEventArgs e)
{
base.OnStartup(e);
new RegionCreationTesterBootstrapper().Run();
}
}
}
RegionCreationTesterBootstrapper.cs
namespace Applications.Testing.Wpf.RegionCreationTester
{
public class RegionCreationTesterBootstrapper : UnityBootstrapper
{
protected override DependencyObject CreateShell()
=> new MainWindow();
protected override void InitializeShell()
{
base.InitializeShell();
(Application.Current.MainWindow = (Window)Shell).Show();
}
}
}
Once all the region population has occurred and the application is about to run I get a Prism.Regions.UpdateRegionsException
containing an InnerException with the message "Region with the given name is already registered: collectionRegion"
on the line in App
of new RegionCreationTesterBootstrapper().Run()
. The last line in my code I am able to get a breakpoint hit for is the new MainWindow()
in CreateShell
after the call to the constructor for MainWindow has exited. Why am I being told the region is already registered when I am only trying to register it once? I have set breakpoints in the MainWindow's constructor to indeed confirm that it only being created once and even if it weren't, the RegionManager
to which it is scoped should prevent this exception from occurring. What have I missed?
UPDATE
I have just commented out the code within PopulateItemsControl
and found that the exception is thrown even if only one view is added to the region and stranger still, if no views are added to the region but the region is accessed (as done in the line: var region = RegionManager.Regions[RegionNames.itemsControlRegion];
). Therefore the issue is now to do with accessing an existing region on a scoped RegionManager for View Injection in order to add views to it; I'm not sure why accessing a region from the RegionManager would change its state, this seems like a bug in Prism or perhaps something to do with lazy enumeration.