PageRenderTime 51ms CodeModel.GetById 27ms RepoModel.GetById 0ms app.codeStats 1ms

/BaconographyWP8Core/Common/RedditViewPivotItemControl.cs

https://github.com/hippiehunter/Baconography
C# | 197 lines | 152 code | 36 blank | 9 comment | 34 complexity | ef9a71a3fff7805851406d28c385b864 MD5 | raw file
  1. using BaconographyPortable.Messages;
  2. using BaconographyPortable.Services;
  3. using BaconographyPortable.ViewModel;
  4. using BaconographyWP8.Messages;
  5. using BaconographyWP8.View;
  6. using BaconographyWP8.ViewModel;
  7. using GalaSoft.MvvmLight;
  8. using GalaSoft.MvvmLight.Messaging;
  9. using Microsoft.Phone.Controls;
  10. using Microsoft.Practices.ServiceLocation;
  11. using System;
  12. using System.Collections.Generic;
  13. using System.Collections.ObjectModel;
  14. using System.Collections.Specialized;
  15. using System.IO;
  16. using System.IO.IsolatedStorage;
  17. using System.Linq;
  18. using System.Text;
  19. using System.Threading;
  20. using System.Threading.Tasks;
  21. using System.Windows;
  22. using System.Windows.Controls;
  23. using System.Windows.Media;
  24. using System.Windows.Media.Imaging;
  25. using Windows.System.Threading;
  26. namespace BaconographyWP8.Common
  27. {
  28. public class RedditViewPivotControl : Pivot
  29. {
  30. IViewModelContextService _viewModelContextService;
  31. ISuspendableWorkQueue _suspendableWorkQueue;
  32. public RedditViewPivotControl()
  33. {
  34. _viewModelContextService = ServiceLocator.Current.GetInstance<IViewModelContextService>();
  35. _suspendableWorkQueue = ServiceLocator.Current.GetInstance<ISuspendableWorkQueue>();
  36. Messenger.Default.Register<SelectIndexMessage>(this, selectIndex);
  37. }
  38. public RedditView CurrentRedditView
  39. {
  40. get { return (RedditView)GetValue(CurrentRedditViewProperty); }
  41. set { SetValue(CurrentRedditViewProperty, value); }
  42. }
  43. // Using a DependencyProperty as the backing store for CurrentRedditView. This enables animation, styling, binding, etc...
  44. public static readonly DependencyProperty CurrentRedditViewProperty =
  45. DependencyProperty.Register("CurrentRedditView", typeof(RedditView), typeof(RedditViewPivotControl), new PropertyMetadata(null));
  46. private void selectIndex(SelectIndexMessage message)
  47. {
  48. if (message.Index < Items.Count && message.Index >= 0)
  49. {
  50. SelectedIndex = message.Index;
  51. }
  52. else if (message.Index == -1)
  53. {
  54. SelectedIndex = Items.Count - 1;
  55. }
  56. }
  57. RedditView MapViewModel(ViewModelBase viewModel)
  58. {
  59. return new RedditView() { Margin = new Thickness(0,0,0,0), Padding = new Thickness(0,0,0,0) };
  60. }
  61. int inflightLoadId = 0;
  62. PivotItem inflightLoad;
  63. protected override async void OnLoadingPivotItem(PivotItem item)
  64. {
  65. //since this is going to take a non trivial amount of time we need to prevent
  66. //any future loads from conflicting with what we're doing
  67. //by taking an always increasing id we can check aginst it prior to continuing
  68. //and implement a sort of cancel.
  69. //this has the added side effect of making super rapid transitions of the pivot nearly free
  70. //since no one pivot will be the current one for more then a few hundred milliseconds
  71. using (_suspendableWorkQueue.HighValueOperationToken)
  72. {
  73. var loadIdAtStart = ++inflightLoadId;
  74. inflightLoad = item;
  75. base.OnLoadingPivotItem(item);
  76. if (item.Content is RedditView)
  77. {
  78. CurrentRedditView = item.Content as RedditView;
  79. return;
  80. }
  81. var imageControl = item.Content as Image;
  82. if (imageControl != null)
  83. await Task.Delay(400);
  84. if (loadIdAtStart != inflightLoadId)
  85. return;
  86. var madeControl = MapViewModel(item.DataContext as ViewModelBase);
  87. if (imageControl != null)
  88. await Task.Yield();
  89. if (loadIdAtStart != inflightLoadId)
  90. return;
  91. madeControl.DataContext = item.DataContext as ViewModelBase;
  92. if (imageControl != null)
  93. await Task.Yield();
  94. if (loadIdAtStart != inflightLoadId)
  95. return;
  96. if (imageControl != null)
  97. imageControl.Source = null;
  98. item.Content = madeControl;
  99. CurrentRedditView = madeControl;
  100. madeControl.LoadWithScroll();
  101. }
  102. }
  103. private async Task RealUnloadingItem(PivotItemEventArgs e)
  104. {
  105. using (_suspendableWorkQueue.HighValueOperationToken)
  106. {
  107. if (e.Item == null)
  108. return;
  109. //if we didnt finish loading we dont need to make a new writable bitmap
  110. if (!(e.Item.Content is Image) && e.Item.Content is UIElement)
  111. {
  112. if (e.Item.Content is RedditView)
  113. {
  114. await Task.Delay(500);
  115. if (inflightLoad == e.Item)
  116. return;
  117. ((RedditView)e.Item.Content).UnloadWithScroll();
  118. }
  119. await Task.Delay(500);
  120. if (inflightLoad == e.Item)
  121. return;
  122. try
  123. {
  124. WriteableBitmap bitmap = new WriteableBitmap(e.Item.Content as UIElement, null);
  125. bitmap.Invalidate();
  126. await Task.Delay(250);
  127. if (inflightLoad == e.Item)
  128. return;
  129. e.Item.Content = new Image { Source = bitmap };
  130. }
  131. catch
  132. {
  133. //sometimes we get a catestrophic error depending on how things were loaded and unloaded here
  134. e.Item.Content = null;
  135. }
  136. }
  137. }
  138. }
  139. protected override async void OnUnloadingPivotItem(PivotItemEventArgs e)
  140. {
  141. base.OnUnloadingPivotItem(e);
  142. await RealUnloadingItem(e);
  143. }
  144. protected override void OnLoadedPivotItem(PivotItem item)
  145. {
  146. _viewModelContextService.PushViewModelContext(item.DataContext as ViewModelBase);
  147. base.OnLoadedPivotItem(item);
  148. }
  149. protected override void OnUnloadedPivotItem(PivotItemEventArgs e)
  150. {
  151. if (e.Item == null)
  152. {
  153. _viewModelContextService.ClearViewModelContext();
  154. return;
  155. }
  156. if (e.Item.DataContext is ViewModelBase)
  157. _viewModelContextService.PopViewModelContext(e.Item.DataContext as ViewModelBase);
  158. base.OnUnloadedPivotItem(e);
  159. }
  160. }
  161. }