Print Page | Close Window

[Resolved] TabShellLayout

Printed From: IdeaBlade
Category: DevForce
Forum Name: DevForce Classic
Forum Discription: For .NET 2.0
URL: http://www.ideablade.com/forum/forum_posts.asp?TID=474
Printed Date: 10-Jun-2026 at 5:44am


Topic: [Resolved] TabShellLayout
Posted By: orcities
Subject: [Resolved] TabShellLayout
Date Posted: 05-Oct-2007 at 7:32am
In a different thread I got off track and started asking about tabs, so I started a new thread to discuss this.
 
I am using the TabShellLayout, that Ward was generous enough to give us, and I am curious as to how the tab display name is set.
 
I have noticed that it is not the same value as the nav bar as one might thing. It apparently is set somewhere else.
 
Does anyone know where this might be?



Replies:
Posted By: Linguinut
Date Posted: 05-Oct-2007 at 9:12am

In the view's tabcontroller:

/// <summary>Set the View's Tab's SmartPartInfo within the
/// <see cref="TabViewController.ShowInTabWorkspace"/> phase.</summary>
protected override TabSmartPartInfo SetSmartPartInfo()
{
   
return SmartPartInfoFns.MakeTabSmartPartInfo("Addresses", "Customer Addresses", true);
}
 
Hope that helps.


Posted By: orcities
Date Posted: 05-Oct-2007 at 9:31am
That is for the actual TabControllers. Mine is the Page itself. I am using a TabLayout for my pages. So each Nav Menu item creates a new Tab Page.


Posted By: Linguinut
Date Posted: 05-Oct-2007 at 9:52am
That is a bit of a mystery, then.
 
SmartPartInfo.Title = "foo";
 
Would that work?


Posted By: orcities
Date Posted: 05-Oct-2007 at 10:19am
SmartPartInfo doesn't exist in the PageController itself. I found the PageView.SmartPartInfo and tried to change the title there. It did not do anything.


Posted By: Bill Jensen
Date Posted: 08-Oct-2007 at 1:31pm
Ward's Response:
 
I suspect that you are referring to the tab titles that appear when the Page content area is implemented with a TabWorkspace rather than a DeckWorkspace.
 
[aside: That's what we do in TabShellLayout.cs which is hiding as an excluded file in Cabana.Foundation.Views.Layout.]
 
You were betting that this the tab text title carried over from the NavBar title. That makes sense although it is by no means necessary that the tab title (which is brief and might be supplemented dynamically with something instance specific) should be the same as the nav bar item text (which could be fixed text and too long).
 
In any case, the PageController is decoupled from all navigation so it doesn't know about a NavBar title. I suppose we could have passed it into the PageController but I didn't like that approach. Clearly I figured that the author of a PageController should decide how to determine the Page name.
 
To control how a Page view displays in the page area, we must set the view's PageSmartPartInfo. I do this for you in the PageControllers (see CabanaLib) - see InitializeSmartPartInfo.
 
[aside: PageSmartPartInfo derives ultimately from CAB's SmartPartInfo which is the standard CAB mechanism for communicating extra configuration data to a View as it is about to be loaded into a Workspace.]
 
This InitializeSmartPartInfo virtual method sets the page name to the Title. Title is a virtual property of the PageController which, by default, shows the RootObjectTypeDisplayName. That too is a virtual property of the PageController that defaults to the name of the type of the root object (recall all pages have a root object - the thing that they are putatively about).
 
Users of the default ShellLayout from CabanaLib (e.g, DotNetShellLayout, DevExShellLayout, ... depending on the control suite) don't complain about this because the Page area is a DeckWorkSpace rather than a TabWorkSpace; no tabs, no tab title, no problem.
 
I'll leave it to you to figure out how you obtain page titles. If you override each PageController's Title property so that it returns that value, things should work out fine.
 
Dan's Response to Ward's Response:
 
Thank you Ward. Apparently I set the title before the initialization took affect so the title never changed. I decided to override the InitializeSmartPartInfo method in my PageController and it worked like a charm.


Posted By: orcities
Date Posted: 22-Oct-2007 at 3:05pm
I am still working with the tabbedshelllayout.
 
I want to close a tab completely and then be able to reload it when the user selects that page again. And I am wondering the best way to do this.
 
I have tried .Close(mShellContentWorkspace.SmartParts[mShellContentWorkspace.SelectedTabPageIndex]);.
 
But when I do this and wish to load the page again it gives me an error because the SmartPart no longer exists.
 
I really do not want it to hide, which I can do, because I want the data reloaded when the page is loaded again.
 
Also, is there a way to access the TabControl from inside a module or outside form. (ie. close all tabs from an admin/options page)?


Posted By: Bill Jensen
Date Posted: 22-Oct-2007 at 4:22pm
Hi Dan,
 
You said:
 
I want to close a tab completely and then be able to reload it when the user selects that page again. And I am wondering the best way to do this.
 
I have tried .Close(mShellContentWorkspace.SmartParts[mShellContentWorkspace.SelectedTabPageIndex]);.
 
Yes, as Platt describes, Workspace.Close() removes the SmartPart from the workspace.  You would probably have to replicate the composition logic from the page controller's Run() method in its ShowPage delegate, taking care not to create a new page every time its shown.
 
I really do not want it to hide, which I can do, because I want the data reloaded when the page is loaded again.
 
Why not?  You could use some logic to determine if it's been hidden and if so, unhide it and refresh the contents of its data source.
 
Also, is there a way to access the TabControl from inside a module or outside form. (ie. close all tabs from an admin/options page)?
 
The shell layout view is registered as a SmartPart in the root workitem under the key

WorkspaceNames.ShellLayout

Bill J.


Posted By: orcities
Date Posted: 23-Oct-2007 at 8:16am
How would I refresh the contents of the datasource? I have been trying to figure that out for a while.


Posted By: Bill Jensen
Date Posted: 23-Oct-2007 at 10:16am

Re-execute the original query and assign the result as the data source for the binding source.

 



Posted By: orcities
Date Posted: 23-Oct-2007 at 10:20am
duh


Posted By: orcities
Date Posted: 26-Oct-2007 at 10:24am
I am trying to find a way to see the state of the current tab. I know I can get to the TabController by using  ShellService.ShellContentWorkspace.
 
But, if I don't want to make it a specific type of workspace how do I get the current page?
 
There is a ShellContentWorkspace.Hide and Show; but, you have to send it a SmartPart. I can access the Show using the NavViewContext on PageController but, how do I know the SmartPart to use when I am at the TabShellLayoutPresenter?


Posted By: orcities
Date Posted: 26-Oct-2007 at 12:42pm
I am now able to get the workspace to hide and show again. I used the DemoDotNetTabVisibility as a guide.
 
I combined the Presenter and the Buildcore info from the demo into the ShellTabLayoutPresenter:

        public void SetToggleTabVisibilityCommandElement(

            object pUiElement, string pUiElementEventName, IWorkspace pWorkspace)

        {

            ShellTabVisibility.SetTabControl(WorkItem, pWorkspace);

 

            CabFns.AddLocalCommandInvoker(

              WorkItem, "ToggleTabVisibility", pUiElement, pUiElementEventName);

        }

 
And added the InjectPresenter call in the ShellTabLayoutView
 

pPresenter.SetToggleTabVisibilityCommandElement(mShellContentWorkspace, "CloseButtonClick", mShellContentWorkspace);

There are other little changes, like making it DevEx.

Now I just have to get the Tab itself to hide a reappear. And then refreshing the data on some occurances.


Posted By: orcities
Date Posted: 26-Oct-2007 at 1:46pm
I can get the tab to hide and the SmartPart to hide. But I can not get them to reload. 
 
I am looking for a way to get the tab/page to reload when you choose its item from the Nav bar. Unfortunately it does not.
 
I believe I will need to set the tab visibility at the PageController or the ModuleController.
 
I know that the Page.ShowPage function is called whenever the nav bar item is selected. So, this would be a good place to set the page back to visible.
 
But, that brings me back to one of my original questions. If I want this to be loose coupling how do I know from the ShellServices.ShellContent that a tab even exists? How do I reload the tab and keep it loosely coupled.
 
 


Posted By: orcities
Date Posted: 26-Oct-2007 at 2:12pm
The TabPresenter registers an event (ToggleVisibility) that fires when the user clicks the close button.
 
The problem is that I am not sure how to get the nav bar to fire an event that fires the ToggleVisbility event as well.
 
Not sure how I would get the Nav bar to fire another event, one is fired automatically for ShowPage<>, that will fire the ToggleVisibility event again.
 
help please.


Posted By: orcities
Date Posted: 26-Oct-2007 at 2:41pm
I have got the command to run when I click a group in the nav bar. I just can't get it to run when I click an item in that group.


Posted By: Linguinut
Date Posted: 26-Oct-2007 at 2:47pm
Dan,
 
For what it's worth, I really wish I could help.  I have been tracking with you.  As I keep up with you, if anything comes to mind, I will certainly let you know.  Keep at it.  The solution is waiting for you to find.
 
Bill


Posted By: orcities
Date Posted: 26-Oct-2007 at 3:49pm
I am going to alter the ShellService and the Nave service to do what I want. I will let you know how it goes.


Posted By: orcities
Date Posted: 29-Oct-2007 at 12:20pm
Ok, I know what I want to do. But I have no idea on how to do it.
 
The following is built into the page controllers ShowPage:

if ( controller == null ) {

        controller = MakeNewPage<T>(pParentWorkItem, pPageWorkItemId);

        ShowPage(controller, pPageWorkspace);

      } else {

        controller.MainWorkspace.Activate(controller.MainView);

      }

Meaning that if the controller doesn't exist then add one. This will do the refresh of the content.
 
Now, in the TabbedShellLayout I can hide a page. I can also get the ActiveSmartPart and the current IPageView, to keep it generic.
 
I want to dispose of that PageView, that way when the user clicks on the nav item again it will create the page again, but I have no idea how to do that.
 
So far, I have been successful in hiding the tab, remove it from the WorkItem. But, the page will not load again when the user clicks on the nav item.
 
HELP


Posted By: Bill Jensen
Date Posted: 29-Oct-2007 at 2:22pm

The concept of destroying and recreating a view each time it becomes visible is rather foreign to CAB and Cabana.

Since you've succeeded in hiding and revealing a view, I'm still not understanding why you can't merely refresh the data source of a view when it becomes visible.
 
Bill J.


Posted By: orcities
Date Posted: 29-Oct-2007 at 2:34pm

Because I am an idiot and can't figure out how to do it.

I know I want to "Re-execute the original query and assign the result as the data source for the binding source." but I can't figure it out.
 
ShowPage is static. This method runs when you click on the link in the NavBar. Therefore, I do not have the same access to the variables. The MainBindingSource is not static.
 
The main reason I was trying to remove the page from the WorkItem is because ShowPage either adds a new page, if the current page hasn't been created, or makes it the active page. I thought it would be simpler to remove it. This would only require me to add code to the TabShellLayout presenter and view.
 
 
 
 


Posted By: Bill Jensen
Date Posted: 29-Oct-2007 at 3:33pm

The static ShowPage() method of the page controller (mine is named Page1) calls the generic base class method:

ShowPage<Page1PageController>(pParentWorkItem, pPageWorkItemId, pPageWorkspace);

Examining this method, we find:

protected static void ShowPage<T>(WorkItem pParentWorkItem, string pPageWorkItemId, IWorkspace pPageWorkspace)

where T : PageController<TRootObj> {

T controller = GetPageController<T>(pParentWorkItem, pPageWorkItemId);

We note that GetPageController<>() is protected static, so it's available in our page controller's static ShowPage method.  So, in your page controller's static ShowPage() method try:
 

public static void ShowPage(WorkItem pParentWorkItem, string pPageWorkItemId, IWorkspace pPageWorkspace)

{

// Refresh entities before displaying

Page1PageController controller = GetPageController<Page1PageController>(pParentWorkItem, pPageWorkItemId);

controller.RefreshEntities();

// Base ShowPage method will call back to overridden methods in this class

ShowPage<Page1PageController>(pParentWorkItem, pPageWorkItemId, pPageWorkspace);

}

Then write a RefreshEntities() method (perhaps similar to what you do in GetInitialEntities() to re-query the data.
 
Full disclosure:  I haven't tested this code.
 
Bill J.


Posted By: orcities
Date Posted: 30-Oct-2007 at 12:55pm
This is my solution, atleast until refactoring.
 
I created a TabService. This service adds each tab to a collection, built with a helper class that add the tab with an allowclose flag. If the page is to not ever be closed then the flag is false. When a new page is selected I see if the page exists in the collection if not I add it.
 
Then in the ShowPage static method of each page I make the page visible by pulling the Tab from the service and changing the visibility. Then I refresh the page, as noted above by Bill, if necessary.
 
 
 
 


Posted By: Bill Jensen
Date Posted: 30-Oct-2007 at 2:37pm
Sounds like a good solution to me.  Keeping the knowledge of the tabs in a TabService avoids having any other components depend on the particular shell layout type.
 
This could be generalized slightly into a "PageVisibilityService" with a MakeVisible(pageViewId) method.   If the page isn't part of a TabShellLyaout, the service does nothing.  That way, page's don't care at all about where they're displayed.
 
Bill J.



Print Page | Close Window