ViewAware.cs 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899
  1. namespace Caliburn.Micro.Core {
  2. using System;
  3. using System.Collections.Generic;
  4. /// <summary>
  5. /// A base implementation of <see cref = "IViewAware" /> which is capable of caching views by context.
  6. /// </summary>
  7. public class ViewAware : PropertyChangedBase, IViewAware {
  8. readonly IDictionary<object, object> views;
  9. /// <summary>
  10. /// The default view context.
  11. /// </summary>
  12. public static readonly object DefaultContext = new object();
  13. /// <summary>
  14. /// The view chache for this instance.
  15. /// </summary>
  16. protected IDictionary<object, object> Views {
  17. get { return views; }
  18. }
  19. /// <summary>
  20. /// Creates an instance of <see cref="ViewAware"/>.
  21. /// </summary>
  22. public ViewAware() {
  23. views = new WeakValueDictionary<object, object>();
  24. }
  25. /// <summary>
  26. /// Raised when a view is attached.
  27. /// </summary>
  28. public event EventHandler<ViewAttachedEventArgs> ViewAttached = delegate { };
  29. void IViewAware.AttachView(object view, object context) {
  30. Views[context ?? DefaultContext] = view;
  31. var nonGeneratedView = PlatformProvider.Current.GetFirstNonGeneratedView(view);
  32. PlatformProvider.Current.ExecuteOnFirstLoad(nonGeneratedView, OnViewLoaded);
  33. OnViewAttached(nonGeneratedView, context);
  34. ViewAttached(this, new ViewAttachedEventArgs {View = nonGeneratedView, Context = context});
  35. var activatable = this as IActivate;
  36. if (activatable == null || activatable.IsActive) {
  37. PlatformProvider.Current.ExecuteOnLayoutUpdated(nonGeneratedView, OnViewReady);
  38. }
  39. else {
  40. AttachViewReadyOnActivated(activatable, nonGeneratedView);
  41. }
  42. }
  43. static void AttachViewReadyOnActivated(IActivate activatable, object nonGeneratedView) {
  44. var viewReference = new WeakReference(nonGeneratedView);
  45. EventHandler<ActivationEventArgs> handler = null;
  46. handler = (s, e) => {
  47. ((IActivate)s).Activated -= handler;
  48. var view = viewReference.Target;
  49. if (view != null) {
  50. PlatformProvider.Current.ExecuteOnLayoutUpdated(view, ((ViewAware)s).OnViewReady);
  51. }
  52. };
  53. activatable.Activated += handler;
  54. }
  55. /// <summary>
  56. /// Called when a view is attached.
  57. /// </summary>
  58. /// <param name="view">The view.</param>
  59. /// <param name="context">The context in which the view appears.</param>
  60. protected virtual void OnViewAttached(object view, object context) {
  61. }
  62. /// <summary>
  63. /// Called when an attached view's Loaded event fires.
  64. /// </summary>
  65. /// <param name = "view"></param>
  66. protected virtual void OnViewLoaded(object view) {
  67. }
  68. /// <summary>
  69. /// Called the first time the page's LayoutUpdated event fires after it is navigated to.
  70. /// </summary>
  71. /// <param name = "view"></param>
  72. protected virtual void OnViewReady(object view) {
  73. }
  74. /// <summary>
  75. /// Gets a view previously attached to this instance.
  76. /// </summary>
  77. /// <param name = "context">The context denoting which view to retrieve.</param>
  78. /// <returns>The view.</returns>
  79. public virtual object GetView(object context = null) {
  80. object view;
  81. Views.TryGetValue(context ?? DefaultContext, out view);
  82. return view;
  83. }
  84. }
  85. }