Advertisement
Guest User

Untitled

a guest
Jun 1st, 2016
88
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 8.76 KB | None | 0 0
  1. using System;
  2. using System.Collections;
  3. using System.Windows;
  4. using System.Windows.Controls;
  5. using System.Windows.Input;
  6. using System.Windows.Markup;
  7. using System.Windows.Media;
  8.  
  9. namespace Dalstroem
  10. {
  11. [ContentProperty(nameof(Content))]
  12. public class ModalContentPresenter : FrameworkElement
  13. {
  14. private readonly Panel _layoutRoot;
  15. private readonly ContentPresenter _primaryContentPresenter;
  16. private readonly ContentPresenter _modalContentPresenter;
  17. private readonly Border _overlay;
  18. private readonly object[] _logicalChildrens = new object[2];
  19.  
  20. private KeyboardNavigationMode _cachedTabNavigationMode;
  21. private KeyboardNavigationMode _cachedDirectionalNavigationMode;
  22. private IInputElement _cachedFocusedElement;
  23.  
  24. #region Dependency properties
  25.  
  26. public static readonly DependencyProperty ContentProperty = DependencyProperty.Register(
  27. "Content", typeof(object), typeof(ModalContentPresenter), new UIPropertyMetadata(null, OnContentChanged));
  28.  
  29. public object Content
  30. {
  31. get { return GetValue(ContentProperty); }
  32. set { SetValue(ContentProperty, value); }
  33. }
  34.  
  35. public static readonly DependencyProperty ModalContentProperty = DependencyProperty.Register(
  36. "ModalContent", typeof(object), typeof(ModalContentPresenter), new UIPropertyMetadata(null, OnModalContentChanged));
  37.  
  38. public object ModalContent
  39. {
  40. get { return GetValue(ModalContentProperty); }
  41. set { SetValue(ModalContentProperty, value); }
  42. }
  43.  
  44. public static readonly DependencyProperty IsModalProperty = DependencyProperty.Register(
  45. "IsModal", typeof(bool), typeof(ModalContentPresenter), new FrameworkPropertyMetadata(false, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, OnIsModalChanged));
  46.  
  47. public bool IsModal
  48. {
  49. get { return (bool)GetValue(IsModalProperty); }
  50. set { SetValue(IsModalProperty, value); }
  51. }
  52.  
  53. public static readonly DependencyProperty OverlayBackgroundProperty = DependencyProperty.Register(
  54. "OverlayBackground", typeof(Brush), typeof(ModalContentPresenter), new UIPropertyMetadata(new SolidColorBrush(Color.FromArgb(200, 255, 255, 255)), OnOverlayBackgroundChanged));
  55.  
  56. public Brush OverlayBackground
  57. {
  58. get { return (Brush)GetValue(OverlayBackgroundProperty); }
  59. set { SetValue(OverlayBackgroundProperty, value); }
  60. }
  61.  
  62. #endregion
  63.  
  64. /// <summary>
  65. /// Initializes a new instance of the ModalContentPresenter class.
  66. /// </summary>
  67. public ModalContentPresenter()
  68. {
  69. _layoutRoot = new ModalContentPresenterPanel();
  70. _primaryContentPresenter = new ContentPresenter();
  71. _modalContentPresenter = new ContentPresenter();
  72. _overlay = new Border
  73. {
  74. Child = _modalContentPresenter,
  75. Background = OverlayBackground,
  76. Visibility = Visibility.Hidden,
  77. };
  78.  
  79. _overlay.MouseDown += OverlayOnMouseDown;
  80. _overlay.KeyUp += OverlayOnKeyUp;
  81.  
  82. AddVisualChild(_layoutRoot);
  83.  
  84. _layoutRoot.Children.Add(_primaryContentPresenter);
  85. _layoutRoot.Children.Add(_overlay);
  86. }
  87.  
  88. /// <summary>
  89. /// Sets the content when changed.
  90. /// </summary>
  91. /// <param name="s"></param>
  92. /// <param name="e"></param>
  93. private static void OnContentChanged(DependencyObject s, DependencyPropertyChangedEventArgs e)
  94. {
  95. var presenter = s as ModalContentPresenter;
  96. if (presenter == null) return;
  97.  
  98. if (e.OldValue != null)
  99. presenter.RemoveLogicalChild(e.OldValue);
  100.  
  101. presenter._primaryContentPresenter.Content = e.NewValue;
  102. presenter.AddLogicalChild(e.NewValue);
  103. presenter._logicalChildrens[0] = e.NewValue;
  104. }
  105.  
  106. /// <summary>
  107. /// Sets the modal content when changed.
  108. /// </summary>
  109. /// <param name="s"></param>
  110. /// <param name="e"></param>
  111. private static void OnModalContentChanged(DependencyObject s, DependencyPropertyChangedEventArgs e)
  112. {
  113. var presenter = s as ModalContentPresenter;
  114. if (presenter == null) return;
  115.  
  116. if (e.OldValue != null)
  117. presenter.RemoveLogicalChild(e.OldValue);
  118.  
  119. presenter._modalContentPresenter.Content = e.NewValue;
  120. presenter.AddLogicalChild(e.NewValue);
  121. presenter._logicalChildrens[1] = e.NewValue;
  122. }
  123.  
  124. /// <summary>
  125. /// Switches between the content and modal content.
  126. /// </summary>
  127. /// <param name="s"></param>
  128. /// <param name="e"></param>
  129. private static void OnIsModalChanged(DependencyObject s, DependencyPropertyChangedEventArgs e)
  130. {
  131. var presenter = s as ModalContentPresenter;
  132. var value = e.NewValue as bool? ?? false;
  133.  
  134. if (presenter == null) return;
  135.  
  136. var traversalDirection = new TraversalRequest(FocusNavigationDirection.First);
  137.  
  138. if (value)
  139. {
  140. presenter._cachedTabNavigationMode = KeyboardNavigation.GetTabNavigation(presenter._primaryContentPresenter);
  141. presenter._cachedDirectionalNavigationMode = KeyboardNavigation.GetDirectionalNavigation(presenter._primaryContentPresenter);
  142. presenter._cachedFocusedElement = Keyboard.FocusedElement;
  143.  
  144. KeyboardNavigation.SetTabNavigation(presenter._primaryContentPresenter, KeyboardNavigationMode.None);
  145. KeyboardNavigation.SetDirectionalNavigation(presenter._primaryContentPresenter, KeyboardNavigationMode.None);
  146.  
  147. presenter._overlay.Visibility = Visibility.Visible;
  148. presenter._overlay.MoveFocus(traversalDirection);
  149. }
  150. else
  151. {
  152. presenter._overlay.Visibility = Visibility.Hidden;
  153.  
  154. KeyboardNavigation.SetTabNavigation(presenter._primaryContentPresenter, presenter._cachedTabNavigationMode);
  155. KeyboardNavigation.SetDirectionalNavigation(presenter._primaryContentPresenter, presenter._cachedDirectionalNavigationMode);
  156.  
  157. Keyboard.Focus(presenter._cachedFocusedElement);
  158.  
  159. presenter._primaryContentPresenter.MoveFocus(traversalDirection);
  160. }
  161. }
  162.  
  163. /// <summary>
  164. /// Sets the overlay background.
  165. /// </summary>
  166. /// <param name="s"></param>
  167. /// <param name="e"></param>
  168. private static void OnOverlayBackgroundChanged(DependencyObject s, DependencyPropertyChangedEventArgs e)
  169. {
  170. var presenter = s as ModalContentPresenter;
  171. if (presenter == null) return;
  172.  
  173. presenter._overlay.Background = (Brush)e.NewValue;
  174. }
  175.  
  176. /// <summary>
  177. /// Hides the modal content when the user clicks outside the modal content area.
  178. /// </summary>
  179. /// <param name="sender"></param>
  180. /// <param name="e"></param>
  181. private void OverlayOnMouseDown(object sender, MouseButtonEventArgs e)
  182. {
  183. var border = sender as Border;
  184.  
  185. if (border?.IsMouseDirectlyOver ?? false)
  186. {
  187. HideModalContent();
  188. }
  189. }
  190.  
  191. /// <summary>
  192. /// Hides the modal content when the user presses the escape key.
  193. /// </summary>
  194. /// <param name="sender"></param>
  195. /// <param name="e"></param>
  196. private void OverlayOnKeyUp(object sender, KeyEventArgs e)
  197. {
  198. if (e.Key == Key.Escape)
  199. {
  200. HideModalContent();
  201. }
  202. }
  203.  
  204. /// <summary>
  205. /// Shows the modal content.
  206. /// </summary>
  207. public void ShowModalContent() => IsModal = true;
  208.  
  209. /// <summary>
  210. /// Hides the modal content.
  211. /// </summary>
  212. public void HideModalContent() => IsModal = false;
  213.  
  214. #region FrameworkElement overrides
  215.  
  216. protected override Visual GetVisualChild(int index)
  217. {
  218. if (index < 0 || index > 1) throw new ArgumentOutOfRangeException(nameof(index), @"Index is out of range.");
  219.  
  220. return _layoutRoot;
  221. }
  222.  
  223. protected override int VisualChildrenCount => 1;
  224.  
  225. protected override IEnumerator LogicalChildren => _logicalChildrens.GetEnumerator();
  226.  
  227. protected override Size ArrangeOverride(Size finalSize)
  228. {
  229. _layoutRoot.Arrange(new Rect(finalSize));
  230. return finalSize;
  231. }
  232.  
  233. protected override Size MeasureOverride(Size availableSize)
  234. {
  235. _layoutRoot.Measure(availableSize);
  236. return _layoutRoot.DesiredSize;
  237. }
  238.  
  239. #endregion
  240. }
  241. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement