namespace Caliburn.Micro.Core { using System; using System.Collections.Generic; using System.Collections.Specialized; using System.Linq; public partial class Conductor { /// /// An implementation of that holds on many items. /// public partial class Collection { /// /// An implementation of that holds on to many items which are all activated. /// public class AllActive : ConductorBase { private readonly BindableCollection items = new BindableCollection(); private readonly bool openPublicItems; /// /// Initializes a new instance of the class. /// /// if set to true opens public items that are properties of this class. public AllActive(bool openPublicItems) : this() { this.openPublicItems = openPublicItems; } /// /// Initializes a new instance of the class. /// public AllActive() { items.CollectionChanged += (s, e) => { switch (e.Action) { case NotifyCollectionChangedAction.Add: e.NewItems.OfType().Apply(x => x.Parent = this); break; case NotifyCollectionChangedAction.Remove: e.OldItems.OfType().Apply(x => x.Parent = null); break; case NotifyCollectionChangedAction.Replace: e.NewItems.OfType().Apply(x => x.Parent = this); e.OldItems.OfType().Apply(x => x.Parent = null); break; case NotifyCollectionChangedAction.Reset: items.OfType().Apply(x => x.Parent = this); break; } }; } /// /// Gets the items that are currently being conducted. /// public IObservableCollection Items { get { return items; } } /// /// Called when activating. /// protected override void OnActivate() { items.OfType().Apply(x => x.Activate()); } /// /// Called when deactivating. /// /// Inidicates whether this instance will be closed. protected override void OnDeactivate(bool close) { items.OfType().Apply(x => x.Deactivate(close)); if (close) { items.Clear(); } } /// /// Called to check whether or not this instance can close. /// /// The implementor calls this action with the result of the close check. public override void CanClose(Action callback) { CloseStrategy.Execute(items.ToList(), (canClose, closable) => { if (!canClose && closable.Any()) { closable.OfType().Apply(x => x.Deactivate(true)); items.RemoveRange(closable); } callback(canClose); }); } /// /// Called when initializing. /// protected override void OnInitialize() { if (openPublicItems) { GetType().GetProperties() .Where(x => x.Name != "Parent" && typeof (T).IsAssignableFrom(x.PropertyType)) .Select(x => x.GetValue(this, null)) .Cast() .Apply(ActivateItem); } } /// /// Activates the specified item. /// /// The item to activate. public override void ActivateItem(T item) { if (item == null) { return; } item = EnsureItem(item); if (IsActive) { ScreenExtensions.TryActivate(item); } OnActivationProcessed(item, true); } /// /// Deactivates the specified item. /// /// The item to close. /// Indicates whether or not to close the item after deactivating it. public override void DeactivateItem(T item, bool close) { if (item == null) { return; } if (close) { CloseStrategy.Execute(new[] {item}, (canClose, closable) => { if (canClose) CloseItemCore(item); }); } else { ScreenExtensions.TryDeactivate(item, false); } } /// /// Gets the children. /// /// The collection of children. public override IEnumerable GetChildren() { return items; } private void CloseItemCore(T item) { ScreenExtensions.TryDeactivate(item, true); items.Remove(item); } /// /// Ensures that an item is ready to be activated. /// /// The item that is about to be activated. /// The item to be activated. protected override T EnsureItem(T newItem) { var index = items.IndexOf(newItem); if (index == -1) { items.Add(newItem); } else { newItem = items[index]; } return base.EnsureItem(newItem); } } } } }