ActiveItem with IsActive=False

Topics: Bugs, UI Architecture
May 17, 2011 at 12:39 PM

I need clarification of "Conductor<Screen>.Collection.OneActive" and "Conductor<Screen>.Collection.AllActive"

For example take "OneActive". Is it means "AlwaysExactlyOneActive" or "OneOrNoneActive"?

I try to findout myself but come to strange caliburn state:

1) ActivateItem(Screen1 );
2) ActivateItem(Screen2 );
3) DeactivateItem(Screen1 );
4) DeactivateItem(Screen2 );

Now Conductor.ActiveItem == Screen2
but Screen2.IsActive is false.

Depends of how I bind to UI it shows different results!

Maybe there is room for more "Collection" types like "AlwaysExactlyOneActive" or "OneOrNoneActive".

May 17, 2011 at 1:16 PM

Activation doesn't happen until the Conductor is Activated, but it allows you to set the ActiveItem in advance.

May 17, 2011 at 1:42 PM
        public List<DetailShellModuleViewModelBasemodules = new List<DetailShellModuleViewModelBase>();
        public void OnImportsSatisfied()         {             modules.ForEach(ActivateItem);         }
        protected override void OnActivate()
            Debug.WriteLine("Screen 0: " + modules[0].IsActive + " Screen 1: " + modules[1].IsActive + " ActiveItem: " + ActiveItem);
            Debug.WriteLine("Screen 0: " + modules[0].IsActive + " Screen 1: " + modules[1].IsActive + " ActiveItem: " + ActiveItem);
            DeactivateItem(modules[0], false);
            Debug.WriteLine("Screen 0: " + modules[0].IsActive + " Screen 1: " + modules[1].IsActive + " ActiveItem: " + ActiveItem);
            //until now all is OK
            ActivateItem(modules[0]); //Error!! Not really activating Screen0, because is alredy in ActiveItem
            Debug.WriteLine("Screen 0: " + modules[0].IsActive + " Screen 1: " + modules[1].IsActive + " ActiveItem: " + ActiveItem);
Output console:
Screen 0: False Screen 1: False ActiveItem: Marbes.Agendio.DetailPripadu.ViewModel.DetailShellViewModel
[2011-05-17T15:34:29.7340935+02:00] Activating Marbes.Agendio.DetailPripadu.ViewModel.SubjektViewModel.
Screen 0: True Screen 1: False ActiveItem: Marbes.Agendio.DetailPripadu.ViewModel.SubjektViewModel
[2011-05-17T15:34:29.7380943+02:00] Deactivating Marbes.Agendio.DetailPripadu.ViewModel.SubjektViewModel.
Screen 0: False Screen 1: False ActiveItem: Marbes.Agendio.DetailPripadu.ViewModel.SubjektViewModel
//until now all is OK

Screen 0: False Screen 1: False ActiveItem: Marbes.Agendio.DetailPripadu.ViewModel.SubjektViewModel
In the last line I expect Screen 0 is Active! Because I call "ActivateItem(modules[0]);"
If I try activate Screen 1 "ActivateItem(modules[1]);" then Screen 1 will be Active (IsActive=true)
May 17, 2011 at 2:33 PM

No. What I'm saying is that your conductor is not active, so its child cannot be active either. You need to activate the conductor. That happens by it either being rooted inside another conductor, started by the bootstrapper or shown with the window manager. From the docs:


...The second important detail is a consequence of the first. Since all OOTB implementations of IConductor inherit from Screen it means that they too have a lifecycle and that lifecycle cascades to whatever items they are conducting. So, if a conductor is deactivated, it’s ActiveItem will be deactivated as well. If you try to close a conductor, it’s going to only be able to close if all of the items it conducts can close. This turns out to be a very powerful feature. There’s one aspect about this that I’ve noticed frequently trips up developers. If you activate an item in a conductor that is itself not active, that item won’t actually be activated until the conductor gets activated. This makes sense when you think about it, but can occasionally cause hair pulling.

May 17, 2011 at 3:42 PM

I fully understand what you say, but I still think there is a bug.

I have Conductor.Collection.OneActive and two Screens in it.

My conductor is active. I am sure.

The problem occurs when all Screens is deactivated.
Conductor remembers last deactivated Screen in ActiveItem and behaviour differentlly when activating this last active item or another item.



public class DetailShellViewModel : Conductor<DetailShellModuleViewModelBase>.Collection.OneActive
  protected override void OnActivate()  
    //my conductor is active now
    //deactivate all conductor's items
    DeactivateItem(screen1, false);
    DeactivateItem(screen2, false);  

    //this.IsActive == true; screen1.IsActive == false; screen2.IsActive == false; this.ActiveItem == screen2

    //now different event occurs depends on what screen I activate !!

    //case 1 - OK
    ActivateItem(screen1); //screen1.IsActive == TRUE; (changed from false to true)
    //case 2 - BUG
    ActivateItem(screen2); //screen2.IsActive == FALSE; (still remain FALSE even if conductor==true)

To simulate you must comment case 1 or case 2.
May 17, 2011 at 3:47 PM

Please create a ticket with a sample that reproduces the problem and I will look into it.