Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- using System;
- using System.Collections;
- using System.Windows;
- using System.Windows.Controls;
- using System.Windows.Input;
- using System.Windows.Markup;
- using System.Windows.Media;
- namespace Dalstroem
- {
- [ContentProperty(nameof(Content))]
- public class ModalContentPresenter : FrameworkElement
- {
- private readonly Panel _layoutRoot;
- private readonly ContentPresenter _primaryContentPresenter;
- private readonly ContentPresenter _modalContentPresenter;
- private readonly Border _overlay;
- private readonly object[] _logicalChildrens = new object[2];
- private KeyboardNavigationMode _cachedTabNavigationMode;
- private KeyboardNavigationMode _cachedDirectionalNavigationMode;
- private IInputElement _cachedFocusedElement;
- #region Dependency properties
- public static readonly DependencyProperty ContentProperty = DependencyProperty.Register(
- "Content", typeof(object), typeof(ModalContentPresenter), new UIPropertyMetadata(null, OnContentChanged));
- public object Content
- {
- get { return GetValue(ContentProperty); }
- set { SetValue(ContentProperty, value); }
- }
- public static readonly DependencyProperty ModalContentProperty = DependencyProperty.Register(
- "ModalContent", typeof(object), typeof(ModalContentPresenter), new UIPropertyMetadata(null, OnModalContentChanged));
- public object ModalContent
- {
- get { return GetValue(ModalContentProperty); }
- set { SetValue(ModalContentProperty, value); }
- }
- public static readonly DependencyProperty IsModalProperty = DependencyProperty.Register(
- "IsModal", typeof(bool), typeof(ModalContentPresenter), new FrameworkPropertyMetadata(false, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, OnIsModalChanged));
- public bool IsModal
- {
- get { return (bool)GetValue(IsModalProperty); }
- set { SetValue(IsModalProperty, value); }
- }
- public static readonly DependencyProperty OverlayBackgroundProperty = DependencyProperty.Register(
- "OverlayBackground", typeof(Brush), typeof(ModalContentPresenter), new UIPropertyMetadata(new SolidColorBrush(Color.FromArgb(200, 255, 255, 255)), OnOverlayBackgroundChanged));
- public Brush OverlayBackground
- {
- get { return (Brush)GetValue(OverlayBackgroundProperty); }
- set { SetValue(OverlayBackgroundProperty, value); }
- }
- #endregion
- /// <summary>
- /// Initializes a new instance of the ModalContentPresenter class.
- /// </summary>
- public ModalContentPresenter()
- {
- _layoutRoot = new ModalContentPresenterPanel();
- _primaryContentPresenter = new ContentPresenter();
- _modalContentPresenter = new ContentPresenter();
- _overlay = new Border
- {
- Child = _modalContentPresenter,
- Background = OverlayBackground,
- Visibility = Visibility.Hidden,
- };
- _overlay.MouseDown += OverlayOnMouseDown;
- _overlay.KeyUp += OverlayOnKeyUp;
- AddVisualChild(_layoutRoot);
- _layoutRoot.Children.Add(_primaryContentPresenter);
- _layoutRoot.Children.Add(_overlay);
- }
- /// <summary>
- /// Sets the content when changed.
- /// </summary>
- /// <param name="s"></param>
- /// <param name="e"></param>
- private static void OnContentChanged(DependencyObject s, DependencyPropertyChangedEventArgs e)
- {
- var presenter = s as ModalContentPresenter;
- if (presenter == null) return;
- if (e.OldValue != null)
- presenter.RemoveLogicalChild(e.OldValue);
- presenter._primaryContentPresenter.Content = e.NewValue;
- presenter.AddLogicalChild(e.NewValue);
- presenter._logicalChildrens[0] = e.NewValue;
- }
- /// <summary>
- /// Sets the modal content when changed.
- /// </summary>
- /// <param name="s"></param>
- /// <param name="e"></param>
- private static void OnModalContentChanged(DependencyObject s, DependencyPropertyChangedEventArgs e)
- {
- var presenter = s as ModalContentPresenter;
- if (presenter == null) return;
- if (e.OldValue != null)
- presenter.RemoveLogicalChild(e.OldValue);
- presenter._modalContentPresenter.Content = e.NewValue;
- presenter.AddLogicalChild(e.NewValue);
- presenter._logicalChildrens[1] = e.NewValue;
- }
- /// <summary>
- /// Switches between the content and modal content.
- /// </summary>
- /// <param name="s"></param>
- /// <param name="e"></param>
- private static void OnIsModalChanged(DependencyObject s, DependencyPropertyChangedEventArgs e)
- {
- var presenter = s as ModalContentPresenter;
- var value = e.NewValue as bool? ?? false;
- if (presenter == null) return;
- var traversalDirection = new TraversalRequest(FocusNavigationDirection.First);
- if (value)
- {
- presenter._cachedTabNavigationMode = KeyboardNavigation.GetTabNavigation(presenter._primaryContentPresenter);
- presenter._cachedDirectionalNavigationMode = KeyboardNavigation.GetDirectionalNavigation(presenter._primaryContentPresenter);
- presenter._cachedFocusedElement = Keyboard.FocusedElement;
- KeyboardNavigation.SetTabNavigation(presenter._primaryContentPresenter, KeyboardNavigationMode.None);
- KeyboardNavigation.SetDirectionalNavigation(presenter._primaryContentPresenter, KeyboardNavigationMode.None);
- presenter._overlay.Visibility = Visibility.Visible;
- presenter._overlay.MoveFocus(traversalDirection);
- }
- else
- {
- presenter._overlay.Visibility = Visibility.Hidden;
- KeyboardNavigation.SetTabNavigation(presenter._primaryContentPresenter, presenter._cachedTabNavigationMode);
- KeyboardNavigation.SetDirectionalNavigation(presenter._primaryContentPresenter, presenter._cachedDirectionalNavigationMode);
- Keyboard.Focus(presenter._cachedFocusedElement);
- presenter._primaryContentPresenter.MoveFocus(traversalDirection);
- }
- }
- /// <summary>
- /// Sets the overlay background.
- /// </summary>
- /// <param name="s"></param>
- /// <param name="e"></param>
- private static void OnOverlayBackgroundChanged(DependencyObject s, DependencyPropertyChangedEventArgs e)
- {
- var presenter = s as ModalContentPresenter;
- if (presenter == null) return;
- presenter._overlay.Background = (Brush)e.NewValue;
- }
- /// <summary>
- /// Hides the modal content when the user clicks outside the modal content area.
- /// </summary>
- /// <param name="sender"></param>
- /// <param name="e"></param>
- private void OverlayOnMouseDown(object sender, MouseButtonEventArgs e)
- {
- var border = sender as Border;
- if (border?.IsMouseDirectlyOver ?? false)
- {
- HideModalContent();
- }
- }
- /// <summary>
- /// Hides the modal content when the user presses the escape key.
- /// </summary>
- /// <param name="sender"></param>
- /// <param name="e"></param>
- private void OverlayOnKeyUp(object sender, KeyEventArgs e)
- {
- if (e.Key == Key.Escape)
- {
- HideModalContent();
- }
- }
- /// <summary>
- /// Shows the modal content.
- /// </summary>
- public void ShowModalContent() => IsModal = true;
- /// <summary>
- /// Hides the modal content.
- /// </summary>
- public void HideModalContent() => IsModal = false;
- #region FrameworkElement overrides
- protected override Visual GetVisualChild(int index)
- {
- if (index < 0 || index > 1) throw new ArgumentOutOfRangeException(nameof(index), @"Index is out of range.");
- return _layoutRoot;
- }
- protected override int VisualChildrenCount => 1;
- protected override IEnumerator LogicalChildren => _logicalChildrens.GetEnumerator();
- protected override Size ArrangeOverride(Size finalSize)
- {
- _layoutRoot.Arrange(new Rect(finalSize));
- return finalSize;
- }
- protected override Size MeasureOverride(Size availableSize)
- {
- _layoutRoot.Measure(availableSize);
- return _layoutRoot.DesiredSize;
- }
- #endregion
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement