Question

I'm working on a composite application in WPF using Prism 5.

User, needs to enter his login and password, than, the application load modules dynamically related to the user account type. ( root, admin, simple user) Each loaded module has a category, Example: Administration Category : - Users - Application Preferences - ...

I want to get all categories on a ListBox in the left of my window, when Selection changed on my Categories ListBox, then show the related TabControl on the right with the specified items (Loaded modules)

As the following: Schema
(source: livefilestore.com)

My Category and Module Classes are defined as the followng:

public class Category
{
    private readonly ObservableCollection<Module> modules = new ObservableCollection<Module>();
    /// <summary>
    /// The category name
    /// </summary>
    public string Name { get; set; }
    /// <summary>
    /// Modules List
    /// </summary>
    public ObservableCollection<Module> Modules
    {
        get { return modules; }
    }
}

public class Module
{
    /// <summary>
    /// The module name
    /// </summary>
    public string Name { get; set; }
    /// <summary>
    /// The module header on the tabControl
    /// </summary>
    public string Header { get; set; }
}

View:

<Grid.RowDefinitions>
        <RowDefinition Height="50" />
        <RowDefinition Height="*" />
    </Grid.RowDefinitions>
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="160" />
        <ColumnDefinition Width="*" />
    </Grid.ColumnDefinitions>
    <Button Width="120" Height="40" Content="Initialize" Command="{Binding InitializeCategoriesCommand}" />
    <ListBox x:Name="CategoriesListBox" Grid.Row="1" Grid.Column="0" 
             ItemsSource="{Binding Categories}" SelectedIndex="{Binding SelectedIndex}" SelectionChanged="Selector_OnSelectionChanged">
        <ListBox.ItemTemplate>
            <DataTemplate>
                <TextBlock Text="{Binding Name}" TextAlignment="Center" FontSize="30" VerticalAlignment="Center"
                           TextWrapping="Wrap" Padding="10" />
            </DataTemplate>
        </ListBox.ItemTemplate>
    </ListBox>
    <ItemsControl x:Name="TabControlsItems" 
                  ItemsSource="{Binding Categories}"
                  Grid.Row="1" Grid.Column="1" HorizontalAlignment="Stretch" VerticalAlignment="Stretch"
                  >
        <ItemsControl.ItemContainerStyle>
            <Style TargetType="{x:Type ContentPresenter}">
                <Setter Property="Visibility" Value="Collapsed"/>
            </Style>
        </ItemsControl.ItemContainerStyle>
        <ItemsControl.ItemTemplate>
            <DataTemplate>
                <TabControl ItemsSource="{Binding Modules}" HorizontalAlignment="Stretch" VerticalAlignment="Stretch"  >
                    <TabControl.ItemTemplate>
                        <DataTemplate>
                            <TextBlock Text="{Binding Header}" />
                        </DataTemplate>
                    </TabControl.ItemTemplate>
                    <TabControl.ContentTemplate>
                        <DataTemplate>
                            <StackPanel>
                                <TextBlock Text="Module Content" FontSize="30" />
                                <TextBlock Text="{Binding Name}" FontSize="20" />
                            </StackPanel>
                        </DataTemplate>
                    </TabControl.ContentTemplate>
                </TabControl>
            </DataTemplate>
        </ItemsControl.ItemTemplate>
    </ItemsControl>

ViewModel:

private readonly ObservableCollection<Category> categories = new ObservableCollection<Category>();
    private IModuleManager moduleManager;
    private IRegionManager regionManager;

    public MainViewModel(IRegionManager regionManager, IModuleManager moduleManager)
    {
        this.regionManager = regionManager;
        this.moduleManager = moduleManager;
        InitializeCategoriesCommand = new DelegateCommand(InitializeCategories);
    }

    private void InitializeCategories()
    {
        Categories.Clear();
        for (var i = 1; i < 5; i++)
        {
            var cat = new Category("Cat " + i);
            cat.InitializeModules();
            Categories.Add(cat);
        }
    }

    public ObservableCollection<Category> Categories
    {
        get { return categories; }
    }

    public DelegateCommand InitializeCategoriesCommand { get; private set; }

The Code above give the following results and it works perfectly:

Image
(source: livefilestore.com)

and

Image
(source: livefilestore.com)

Modules:

In each module i associate the main view to a region that has the same name as my Category.

RegionManager.RequestNavigate("CategoryName", "ModuleMainView");

My Question:

How can i add a region name in my itemscontrol datatemplate and associate it to a TabControl? I tried to do the following to bind directly the categoryName:

<TabControl prism.RegionManager.RegionName="{Binding Name}" 
HorizontalAlignment="Stretch" VerticalAlignment="Stretch"  />

This allows Prism to add views from loaded models directly in a new item in the TabControl. but after hours of googling, i found this post where Damian explains that the region is created but never registered! i tried also to use his code, but his solution doesn't work on prism 5, Any suggestions please?

Was it helpful?

Solution

You can find an answer for the same question in the following Codeplex thread:

You may find below the WPF sample solution made by Damian Cherubini, updated to Prism 5. Damian's approach could be found in this blogpost, and the update to Prism 5 was just made by referencing the corresponding assemblies:

In addition, regarding Damian's other approach you mentioned, a similar update to Prism 5 could be made after migrating the Silverlight sample into WPF, as Silverlight would not be supported yet.

Regards.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top