Unloading views in deckworkspace??

Topics: CAB & Smart Client Software Factory
Sep 25, 2007 at 12:33 AM
Hi,

I was wondering if there was a way to unload a view from a deckworkspace but in the following scenario:

1. Got a toolbar where buttons are added when each module is loaded.
2. When clicking on one of the added button, it loads a view in mainWorkspace i.e. view1
3. When clicking on another of the added button, it loads a view in mainWorkspace i.e. view2

But I want to unload view1 (not hide) before it adds view 2 to the mainWorkspace and if I click back on the first button, I want to unload view2 and load view1.

How do I do this if I have 10 modules? I want to ensure that I can loop through all the modules and check if their relevant views are loaded. If any specific views are loaded, I want to unload them before loading the newly selected one. With this logic, there should never be more than one view loaded at any one time in mainWorkspace.

Any suggestions?

Thanks.

T.
Developer
Sep 26, 2007 at 12:11 PM
Hi

The IWorkspace interface does not have any Unload method. The Close method is provided to remove a SmartPart from the DeckWorkspace.

In my opinion if you don't want to hide the SmartParts, you would add in the ModuleController class of each module the following code:

private MyView _view = null;
 
public override void Run()
{
    ExtendToolStrip();
}
 
private void ExtendToolStrip()
{
    // Add the button for the moduleN.
    ToolStripButton button = new ToolStripButton("Load View - Module N");
    WorkItem.UIExtensionSites[UIExtensionSiteNames.MainToolbar].Add<ToolStripButton>(button);
 
   // Add the button as an invoker of a command.
    WorkItem.Commands[CommandNames.LoadViewModuleN].AddInvoker(button, "Click");
}
 
[CommandHandler(CommandNames.LoadViewModuleN)]
public void OnViewModuleNLoad(object sender, EventArgs args)
{
    if (_view == null)
        _view = WorkItem.SmartParts.AddNew<MyView>();
 
    IWorkspace w = WorkItem.Workspaces[WorkspaceNames.MainWorkspace];
 
    if (w.ActiveSmartPart == _view)
        return;
            
    if (w.ActiveSmartPart != null)
        w.Close(w.ActiveSmartPart);
                
    w.Show(_view);
}
where N in the previous code would be the number of the module.

Please let me know if this helps!

Mariano Converti
http://staff.southworks.net/blogs/mconverti/
Sep 26, 2007 at 12:52 PM
Hi Mariano,

Thanks for the reply. After posting this, I actually did what you suggested, but this does not seem to work. I'll read again carefully what you suggested, but below is what I did:

Inside my button, I get the workspace (mainWorkspace), and look to see if it had any smartparts. If it does, I close the smartpart(0) and I loop through until the number of workspace count is zero. When debugging, it seems to remove the smartpart and then I show the one relevant to the button it was clicked.

I thought this would work and I could have put it in class so that it could be called from any buttons. The reason I think it does not work (I could be wrong) but one of my view contains a webbrowser and when the view loads I call the following code:

Protected Overrides Sub OnLoad(ByVal e As EventArgs)
_presenter.OnViewReady()
WebBrowser1.Navigate(New Uri("http://localhost/mywebsite.net/"))
MyBase.OnLoad(e)
End Sub

So you would assume, this would be called again after the I've looped through the workspace and close all its smartparts but it seems to still display the webbrowser with the last page I went to rather than re-displaying the default page.

Thanks.

T.
Sep 26, 2007 at 1:11 PM
Hi Mariano,

I just tried what you suggested is the same. Am i doing something wrong?

As mentioned, I click on my admin module, this loads up a specific url i.e http://mywebsite/default.aspx inside a webbrowser control contained in the view of a specific module. I go to lets say http://mywebsite/manageusers.aspx for example and I click on another button in my toolbar. This calls the code you have suggested. I can see that my activesmartpart is now null but when I click back on the admin button which is to reload the admin view, it still reloads the manageuser.aspx instead of default.aspx.

Also why isn't this called again:

Protected Overrides Sub OnLoad(ByVal e As EventArgs)
_presenter.OnViewReady()
WebBrowser1.Navigate(New Uri("http://localhost/mywebsite.net/"))
MyBase.OnLoad(e)
End Sub

Is closing a view different from unload it and therefore causing the OnLoad not to trigger?

Also why isn't my OnCloseView event in my presenter's view not being triggered when the view is being closed?

This is weird??!?!

Thanks.

T.
Sep 26, 2007 at 3:06 PM
Hi Again,

I don't know if what I did is good or not? Can you advice?

I've added overloaded the ShowViewInWorkspace function and added a parameter called closeIfFound (boolean). If try, I call the following code:

If WorkItem.SmartParts.Contains(viewId) Then
view = WorkItem.SmartParts.Get(Of TView)(viewId)
WorkItem.SmartParts.Remove(view)
view = WorkItem.SmartParts.AddNew(Of TView)(viewId)
Else
view = WorkItem.SmartParts.AddNew(Of TView)(viewId)
End If


and this seems to do the trick in terms of triggering all the right events again i.e. onload, etc... but I'd still like to understand why this does not work when used with your method? Also I can't see why there is no closing event being triggered.

Thanks.

T.
Developer
Sep 26, 2007 at 5:16 PM
Hi

The Load event occurs before the control becomes visible for the first time.

Change the method OnViewModuleNLoad of each module for the following:

[CommandHandler(CommandNames.LoadViewModuleN)]
public void OnViewModuleNLoad(object sender, EventArgs args)
{
    IWorkspace w = WorkItem.Workspaces[WorkspaceNames.RightWorkspace];
    
    if (_view == null)
    {
        _view = WorkItem.SmartParts.AddNew<MyView>();
        w.SmartPartActivated += new EventHandler<WorkspaceEventArgs>(_view.OnActivated);
    }
 
    w.Show(_view);
}
When the Workspace detect a SmartPart activating, then will be called the OnActivated method.
Add the OnActivated method in your SmartPart:

public void OnActivated(object sender, WorkspaceEventArgs args)
{
    if (args.SmartPart == this)
    {
        OnLoad(EventArgs.Empty);
    }
}
I believe that in this way your view will be always loaded whenever you click in a button. But if you click twice in a button your view will not reload.


Also why isn't my OnCloseView event in my presenter's view not being triggered when the view is being closed?

OnCloseView isn’t a event. It’s a method that you must call from your view when you want to close it.

Please let me know if this helps!

Mariano Converti
http://staff.southworks.net/blogs/mconverti/
Sep 29, 2007 at 1:12 AM
Hi Mariano,

Terribly sorry for not getting back to you any sooner on your suggestions, but I've messed up my application and I'm still trying to fix it. The minute I can go back to this, I will update this thread.

Thanks again for your help.

Regards,

Thierry
Oct 10, 2007 at 11:19 PM
Hi Mariano,

I'm back with this issue! Sorry it's been a while.

Anyway, I thought I finally sorted it but I just realised that the method I used wasn't great! I was using the on SmartPartClosing but I'm not mad about the method as it seems to be called even when it's not the specific module being closed. It seems to be called whenever any module get closes which is not what I want.

I read your suggestions again and I've applied it but in a slightly different way where I've overloaded the ShowViewInWorkspace with 2 additional parameter where it the first one, if true, basically removes the view that's trying to be displayed if it found so the load event will always occur and the second parameter if true, will close the activesmartpart but my problem is that I still don't know where to call the OnCloseView. I understand I have to call this event from the view with _presenter.OnCloseView but with which event as there is none that I can see?

Is there a specific one that I should add. I've read a few other articles and they all mention the OnCloseView but they don't say where/when to call this sub?

Any ideas?

Thanks.

Thierry.