weird view loading error - Tab doesnot activate content control

Topics: Prism v4 - WPF 4
Sep 8, 2012 at 4:01 PM

 <TabControl Margin="2" prism:RegionManager.RegionName="ShellRegion"  ItemContainerStyle="{DynamicResource ShellTabItemStyle}" >
            <Grid>
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width=".3*"></ColumnDefinition>
                    <ColumnDefinition Width=".7*"></ColumnDefinition>
                </Grid.ColumnDefinitions>
                <!-- Left Region -->
                <Border Grid.Column="0" BorderThickness="1" BorderBrush="Black">
                    <ContentControl x:Name="LeftRegion" prism:RegionManager.RegionName="LeftRegion"  VerticalContentAlignment="Stretch" HorizontalContentAlignment="Stretch" />
                </Border>
                <Border Grid.Column="1" BorderThickness="1" BorderBrush="Black">
                    <ContentControl x:Name="MainRegion" prism:RegionManager.RegionName="ModuleMainRegion"  VerticalContentAlignment="Stretch" HorizontalContentAlignment="Stretch" />
                </Border>
            </Grid>
            </TabControl>

I have above shell structure. when I run the project, both views in left and main region load fine. In Main region, I'm loading a grid.

when I click on a row in the grid, I open another tab. but in this tab, only main region is shown. left region is not loaded at all. what am I doing wrong?

kindly help

Kav

Sep 8, 2012 at 4:22 PM

Ok. I was using wrong region in requestNavigate. I'm using INavigationAware. but now it's different behaviour.

when I click on a row in the grid, I want both left and main regions(with a different view) to open in another tab. but it does not. instead it loads in same tab.what am I doing wrong?

 

is it because of this?(this is called when I click on one fo the row in 1st tab

     regionManager.Regions["MainRegion"].RequestNavigate(new Uri("/View2" + parameters.ToString(), UriKind.Relative), NavigationCompleted);
       
if so, How do I activate view in leftregion? in second tab?

kindly help

Kav

Developer
Sep 10, 2012 at 8:25 PM

Hi Kav,

First of all, if you want to add a new tab (like a tab view) I believe you should add it to the "ShellRegion" (which is the TabControl) defined in the previous code snippet. You could do this by using either navigation or view injection.

Then, after the tab is added you could add the corresponding views to the regions inside the new tab. Therefore you need to perform several navigation requests / view injections, one for the tab and others for the internal regions of the tab.

However, take into account that if both tabs have the same names for their internal regions (that is, LeftRegion and ModuleMainRegion) the RegionManager will raise an exception saying that there are two regions with the same name. Are you handling this using a scoped region manager for each tab or unregistering the regions of the previous tab?

Also, it would be helpful if you could provide us with more information about how you are populating the regions (i.e. the navigation requests, etc) so that we can help you further with this.

I hope you find this useful,

Damian Cherubini
http://blogs.southworks.net/dcherubini

Sep 10, 2012 at 8:50 PM

Hi Damian, 

Yes. as you've mentioned, I've been able to add a new view into new tab by adding it to the shell region. and you're right about left region too. I've got it working with both scoped region and unregistration. ( I tried both these options)

but how do I have 2 views loaded within a tab item? and further in all tab items i open?

I tried both these approaches

 <TabControl Margin="2" prism:RegionManager.RegionName="ShellRegion"  ItemContainerStyle="{DynamicResource ShellTabItemStyle}" >
            <Grid>
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width=".3*"></ColumnDefinition>
                    <ColumnDefinition Width=".7*"></ColumnDefinition>
                </Grid.ColumnDefinitions>
                <!-- Left Region -->
                <Border Grid.Column="0" BorderThickness="1" BorderBrush="Black">
                    <ContentControl x:Name="LeftRegion" prism:RegionManager.RegionName="LeftRegion"  VerticalContentAlignment="Stretch" HorizontalContentAlignment="Stretch" />
                </Border>
                <Border Grid.Column="1" BorderThickness="1" BorderBrush="Black">
                    <ContentControl x:Name="MainRegion" prism:RegionManager.RegionName="ModuleMainRegion"  VerticalContentAlignment="Stretch" HorizontalContentAlignment="Stretch" />
                </Border>
            </Grid>
            </TabControl>

in above tab control, i registered LeftPanel in leftregion(in module class) and used viewexport attribute(like in stocktrader) on viewA to load in ModuleMainRegion. when I click on a button in view A, I'm using INavigationAware methods. 

 

 regionManager.Regions["ModuleMainRegion"].RequestNavigate(new Uri("/View2" + parameters.ToString(), UriKind.Relative), NavigationCompleted);
Obviously, this doesnt open View2 in new tab as i'm navigating within ModuleMainRegion. (View2 opened in same tab)

 

and (Approach B)

 

 

 <TabControl Margin="2" prism:RegionManager.RegionName="ShellRegion"  ItemContainerStyle="{DynamicResource ShellTabItemStyle}" >
            <Grid>
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width=".3*"></ColumnDefinition>
                    <ColumnDefinition Width=".7*"></ColumnDefinition>
                </Grid.ColumnDefinitions>
                <!-- Left Region -->
                <Border Grid.Column="0" BorderThickness="1" BorderBrush="Black">
                    <ContentControl x:Name="LeftRegion" prism:RegionManager.RegionName="LeftRegion"  VerticalContentAlignment="Stretch" HorizontalContentAlignment="Stretch" />
                </Border>
          
            </Grid>
            </TabControl>
I did same thing but registerd ViewA with ShellRegion(Notice there's no modulemainregion here) and on a button click, I called something like this
regionManager.Regions["ShellRegion"].RequestNavigate(new Uri("/View2" + parameters.ToString(), UriKind.Relative), NavigationCompleted);
This opens View2 in new tab. but left region is lost. I've used registerviewwithregion for left control. so thought this should activate everytime i open new tab.
I'm more than happy to attach the exe if I can do so anywhere. 

Does this help? Please help with this issue of mine. Call me Dumb but I've not been able to crack this.
(At the moment, what I'm doing is, i've maintained left region within ViewA itself. and I just have tab region in shell.xaml. this way, everytime i click on anything in viewA, viewB opens in new tab.but disadvantage - I've to ensure to 
add left region in every Usercontrol I develop. bad design)
please help. 

Kavya
Developer
Sep 10, 2012 at 9:08 PM

Hi Kavya,

You could upload your repro sample application to SkyDrive (or any other storage site you'd like to, and post the link here), so we can analyse your scenario in further detail.

Regards,

Agustin Adami
http://blogs.southworks.net/aadami

Sep 10, 2012 at 10:41 PM
Edited Sep 10, 2012 at 10:48 PM

Hi Agustin,

 

http://sdrv.ms/O9J6Xc

 

I've uploaded here. Notice 2 regions in both the usercontrols(deliveries.xaml). at the moment i'm usng this approach to achieve multiple usercontrols on a tab. 

But What I want is to have content controls within tab control region rather than within usercontrol. the current design isn't flexible as I do not want to keep putting contentcontrols in every usercontrol I write. ideally left region will have filters I would search grid by(which is loaded in the main region).

Unless I'm getting the basic design itself wrong? as mentioned in above post, below structure would have been ideal solution for me. but I'm sure you would know better. (would load right hand control to shell region and search panel in left region)

 

 

<TabControl Margin="2" prism:RegionManager.RegionName="ShellRegion"  ItemContainerStyle="{DynamicResource ShellTabItemStyle}" >
            <Grid>
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width=".3*"></ColumnDefinition>
                    <ColumnDefinition Width=".7*"></ColumnDefinition>
                </Grid.ColumnDefinitions>
                <!-- Left Region -->
                <Border Grid.Column="0" BorderThickness="1" BorderBrush="Black">
                    <ContentControl x:Name="LeftRegion" prism:RegionManager.RegionName="LeftRegion"  VerticalContentAlignment="Stretch" HorizontalContentAlignment="Stretch" />
                </Border>
          
            </Grid>
            </TabControl>

 

please help

Kavya

Developer
Sep 11, 2012 at 9:04 PM

Hi Kavya,

I am not sure if I have understood your requirements correctly; however, I modified your repro-sample application to use the following structure:

TabControl

---DoubleRegionTabView

------LeftRegion

------RightRegion

You can find the modified sample in my skydrive account under the name Kavya_TabApproach1:

In the sample, when navigating to the DoubleRegionTabView, a "RightRegion" and "LeftRegion" parameter are added to the navigation Uri specifying the names of the views that the TabItem should have in its regions. Then, the view model of the tab item will populate the regions with the corresponding views, pass the corresponding parameters to each view and ask the view in the RightRegion for its HeaderInfo property.

Like this, all the views should be more reusable.

Take into account that this is just a possible approach and might not be suitable for all scenarios as it has not been tested in deep.

I hope you find this useful,

Damian Cherubini
http://blogs.southworks.net/dcherubini

Developer
Sep 11, 2012 at 9:31 PM

Hi,

After analyzing this scenario, in my opinion an alternative approach could be using a similar structure for the views used in the TabControl, like the one mentioned by DCherubini recently, however instead of using region navigation to compose the views, I believe you could implement a Controller class which will be responsible of coordinating the construction and initialization of the new tabs that will be displayed in the "MainRegion" (region defined in the TabControl). This way you should be able to add new tabs using Scoped Regions and View Injection, and based on the selected DataPool code and any required business logic for your view, you could compose the corresponding views for each region (e.g. "LeftRegion" and SubMainRegion"). Also by using this approach you should be able to set the corresponding value of the HeaderInfo property as you will have access to the views added in the inner regions, and the DataContext of the Tab views.

For a better understanding of this approach I recommend you to check the ProductsController class in Exercise 3 (SHOWING A VIEW IN A SCOPED REGION) of the UI Composition Hands-On Lab from the Prism Training Kit.

Regards,

Agustin Adami
http://blogs.southworks.net/aadami

Sep 11, 2012 at 10:03 PM
Edited Sep 11, 2012 at 10:05 PM

Damian, Agustin

This is exactly what I wanted.

Thank you so much for your help. You now make it look so simple. thanks again for taking time on this thread. I'd left query in pretty much all forums I could think of. 

owe you one. can't thank enough. Not in my wildest dream, I would've thought of having tabitem as different UI.

I'll definitely extend this from here.. 

Thanks for the Prism Training Kit link as well.

 

I can now have a sound sleep. 

Kavya