ConductorWithCollectionAllActive.cs 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177
  1. namespace Caliburn.Micro.Core {
  2. using System;
  3. using System.Collections.Generic;
  4. using System.Collections.Specialized;
  5. using System.Linq;
  6. public partial class Conductor<T> {
  7. /// <summary>
  8. /// An implementation of <see cref="IConductor"/> that holds on many items.
  9. /// </summary>
  10. public partial class Collection {
  11. /// <summary>
  12. /// An implementation of <see cref="IConductor"/> that holds on to many items which are all activated.
  13. /// </summary>
  14. public class AllActive : ConductorBase<T> {
  15. private readonly BindableCollection<T> items = new BindableCollection<T>();
  16. private readonly bool openPublicItems;
  17. /// <summary>
  18. /// Initializes a new instance of the <see cref="Conductor&lt;T&gt;.Collection.AllActive"/> class.
  19. /// </summary>
  20. /// <param name="openPublicItems">if set to <c>true</c> opens public items that are properties of this class.</param>
  21. public AllActive(bool openPublicItems)
  22. : this() {
  23. this.openPublicItems = openPublicItems;
  24. }
  25. /// <summary>
  26. /// Initializes a new instance of the <see cref="Conductor&lt;T&gt;.Collection.AllActive"/> class.
  27. /// </summary>
  28. public AllActive() {
  29. items.CollectionChanged += (s, e) => {
  30. switch (e.Action) {
  31. case NotifyCollectionChangedAction.Add:
  32. e.NewItems.OfType<IChild>().Apply(x => x.Parent = this);
  33. break;
  34. case NotifyCollectionChangedAction.Remove:
  35. e.OldItems.OfType<IChild>().Apply(x => x.Parent = null);
  36. break;
  37. case NotifyCollectionChangedAction.Replace:
  38. e.NewItems.OfType<IChild>().Apply(x => x.Parent = this);
  39. e.OldItems.OfType<IChild>().Apply(x => x.Parent = null);
  40. break;
  41. case NotifyCollectionChangedAction.Reset:
  42. items.OfType<IChild>().Apply(x => x.Parent = this);
  43. break;
  44. }
  45. };
  46. }
  47. /// <summary>
  48. /// Gets the items that are currently being conducted.
  49. /// </summary>
  50. public IObservableCollection<T> Items {
  51. get { return items; }
  52. }
  53. /// <summary>
  54. /// Called when activating.
  55. /// </summary>
  56. protected override void OnActivate() {
  57. items.OfType<IActivate>().Apply(x => x.Activate());
  58. }
  59. /// <summary>
  60. /// Called when deactivating.
  61. /// </summary>
  62. /// <param name="close">Inidicates whether this instance will be closed.</param>
  63. protected override void OnDeactivate(bool close) {
  64. items.OfType<IDeactivate>().Apply(x => x.Deactivate(close));
  65. if (close) {
  66. items.Clear();
  67. }
  68. }
  69. /// <summary>
  70. /// Called to check whether or not this instance can close.
  71. /// </summary>
  72. /// <param name="callback">The implementor calls this action with the result of the close check.</param>
  73. public override void CanClose(Action<bool> callback) {
  74. CloseStrategy.Execute(items.ToList(), (canClose, closable) => {
  75. if (!canClose && closable.Any()) {
  76. closable.OfType<IDeactivate>().Apply(x => x.Deactivate(true));
  77. items.RemoveRange(closable);
  78. }
  79. callback(canClose);
  80. });
  81. }
  82. /// <summary>
  83. /// Called when initializing.
  84. /// </summary>
  85. protected override void OnInitialize() {
  86. if (openPublicItems) {
  87. GetType().GetProperties()
  88. .Where(x => x.Name != "Parent" && typeof (T).IsAssignableFrom(x.PropertyType))
  89. .Select(x => x.GetValue(this, null))
  90. .Cast<T>()
  91. .Apply(ActivateItem);
  92. }
  93. }
  94. /// <summary>
  95. /// Activates the specified item.
  96. /// </summary>
  97. /// <param name="item">The item to activate.</param>
  98. public override void ActivateItem(T item) {
  99. if (item == null) {
  100. return;
  101. }
  102. item = EnsureItem(item);
  103. if (IsActive) {
  104. ScreenExtensions.TryActivate(item);
  105. }
  106. OnActivationProcessed(item, true);
  107. }
  108. /// <summary>
  109. /// Deactivates the specified item.
  110. /// </summary>
  111. /// <param name="item">The item to close.</param>
  112. /// <param name="close">Indicates whether or not to close the item after deactivating it.</param>
  113. public override void DeactivateItem(T item, bool close) {
  114. if (item == null) {
  115. return;
  116. }
  117. if (close) {
  118. CloseStrategy.Execute(new[] {item}, (canClose, closable) => {
  119. if (canClose)
  120. CloseItemCore(item);
  121. });
  122. }
  123. else {
  124. ScreenExtensions.TryDeactivate(item, false);
  125. }
  126. }
  127. /// <summary>
  128. /// Gets the children.
  129. /// </summary>
  130. /// <returns>The collection of children.</returns>
  131. public override IEnumerable<T> GetChildren() {
  132. return items;
  133. }
  134. private void CloseItemCore(T item) {
  135. ScreenExtensions.TryDeactivate(item, true);
  136. items.Remove(item);
  137. }
  138. /// <summary>
  139. /// Ensures that an item is ready to be activated.
  140. /// </summary>
  141. /// <param name="newItem">The item that is about to be activated.</param>
  142. /// <returns>The item to be activated.</returns>
  143. protected override T EnsureItem(T newItem) {
  144. var index = items.IndexOf(newItem);
  145. if (index == -1) {
  146. items.Add(newItem);
  147. }
  148. else {
  149. newItem = items[index];
  150. }
  151. return base.EnsureItem(newItem);
  152. }
  153. }
  154. }
  155. }
  156. }