private void OpenPopup(Point position)
{
_popupAlignmentPoint = position;
InitializeRootVisual();
InitializePage();
bool portrait = _rootVisual.Orientation.IsPortrait();
if (portrait)
{
if (_innerGrid != null)
{
_innerGrid.MinHeight = 0;
}
}
else
{
if (_innerGrid != null)
{
// if landscape to the full height. NOTE: device is rotated so use the ActualWidth
_innerGrid.MinHeight = _rootVisual.ActualWidth;
}
}
_overlay = new Canvas { Background = new SolidColorBrush(Colors.Transparent) };
_overlay.MouseLeftButtonUp += OnOverlayMouseButtonUp;
if (IsZoomEnabled && (null != _rootVisual))
{
// Capture effective width/height
double width = portrait ? _rootVisual.ActualWidth : _rootVisual.ActualHeight;
double height = portrait ? _rootVisual.ActualHeight : _rootVisual.ActualWidth;
// Create a layer for the background brush
UIElement backgroundLayer = new Rectangle
{
Width = width,
Height = height,
Fill = _backgroundBrush,
CacheMode = new BitmapCache(),
};
_overlay.Children.Insert(0, backgroundLayer);
// Hide the owner for the snapshot we will take
FrameworkElement ownerElement = _owner as FrameworkElement;
if (null != ownerElement)
{
ownerElement.Opacity = 0;
}
// Create a layer for the page content
WriteableBitmap writeableBitmap = new WriteableBitmap((int)width, (int)height);
writeableBitmap.Render(_rootVisual, null);
writeableBitmap.Invalidate();
Transform scaleTransform = new ScaleTransform
{
CenterX = width / 2,
CenterY = height / 2,
};
UIElement contentLayer = new Image
{
Source = writeableBitmap,
RenderTransform = scaleTransform,
CacheMode = new BitmapCache(),
};
_overlay.Children.Insert(1, contentLayer);
// Create a layer for the background brush
UIElement backgroundFadeLayer = new Rectangle
{
Width = width,
Height = height,
Fill = _backgroundBrush,
Opacity = 0,
CacheMode = new BitmapCache(),
};
_overlay.Children.Insert(2, backgroundFadeLayer);
// Create a layer for the owner element and its background
if (null != ownerElement)
{
((FrameworkElement)Owner).Opacity = 1;
// If the owner's flow direction is right-to-left, then (0, 0) is situated at the
// top-right corner of the element instead of its top-left corner.
// We need for the translated point to be in the top-left corner since we want these elements
// to be drawn on top of the owner's position from left to right,
// so to achieve that, we'll translate (0, ActualWidth) instead if its flow direction is right-to-left.
Point point = SafeTransformToVisual(ownerElement, _rootVisual).Transform(new Point(ownerElement.FlowDirection == System.Windows.FlowDirection.RightToLeft ? ownerElement.ActualWidth : 0, 0));
// Create a layer for the element's background
UIElement elementBackground = new Rectangle
{
Width = ownerElement.ActualWidth,
Height = ownerElement.ActualHeight,
Fill = new SolidColorBrush(Colors.Transparent),
CacheMode = new BitmapCache(),
};
Canvas.SetLeft(elementBackground, point.X);
Canvas.SetTop(elementBackground, point.Y);
_overlay.Children.Insert(3, elementBackground);
// Create a layer for the element
UIElement element = new Image { Source = new WriteableBitmap(ownerElement, null) };
Canvas.SetLeft(element, point.X);
Canvas.SetTop(element, point.Y);
_overlay.Children.Insert(4, element);
}
// Prepare for scale animation
double from = 1;
double to = 0.94;
TimeSpan timespan = TimeSpan.FromSeconds(0.42);
IEasingFunction easingFunction = new ExponentialEase { EasingMode = EasingMode.EaseInOut };
_backgroundResizeStoryboard = new Storyboard();
// Create an animation for the X scale
DoubleAnimation animationX = new DoubleAnimation { From = from, To = to, Duration = timespan, EasingFunction = easingFunction };
Storyboard.SetTarget(animationX, scaleTransform);
Storyboard.SetTargetProperty(animationX, new PropertyPath(ScaleTransform.ScaleXProperty));
_backgroundResizeStoryboard.Children.Add(animationX);
// Create an animation for the Y scale
DoubleAnimation animationY = new DoubleAnimation { From = from, To = to, Duration = timespan, EasingFunction = easingFunction };
Storyboard.SetTarget(animationY, scaleTransform);
Storyboard.SetTargetProperty(animationY, new PropertyPath(ScaleTransform.ScaleYProperty));
_backgroundResizeStoryboard.Children.Add(animationY);
if (IsFadeEnabled)
{
DoubleAnimation animationFade = new DoubleAnimation { From = 0, To = .3, Duration = timespan, EasingFunction = easingFunction };
Storyboard.SetTarget(animationFade, backgroundFadeLayer);
Storyboard.SetTargetProperty(animationFade, new PropertyPath(Rectangle.OpacityProperty));
_backgroundResizeStoryboard.Children.Add(animationFade);
}
}
// Create transforms for handling rotation
TransformGroup transforms = new TransformGroup();
if (null != _rootVisual)
{
switch (_rootVisual.Orientation)
{
case PageOrientation.LandscapeLeft:
transforms.Children.Add(new RotateTransform { Angle = 90 });
transforms.Children.Add(new TranslateTransform { X = _rootVisual.ActualWidth });
break;
case PageOrientation.LandscapeRight:
transforms.Children.Add(new RotateTransform { Angle = -90 });
transforms.Children.Add(new TranslateTransform { Y = _rootVisual.ActualHeight });
break;
}
}
_overlay.RenderTransform = transforms;
// Add Click handler for ApplicationBar Buttons
if ((null != _page) && (null != _page.ApplicationBar) && (null != _page.ApplicationBar.Buttons))
{
foreach (object obj in _page.ApplicationBar.Buttons)
{
ApplicationBarIconButton button = obj as ApplicationBarIconButton;
if (null != button)
{
button.Click += OnEventThatClosesContextMenu;
_applicationBarIconButtons.Add(button);
}
}
}
_overlay.Children.Add(this);
_popup = new Popup { Child = _overlay };
_popup.Opened += (s, e) =>
{
// When the popup is actually opened, call our OnOpened method
OnOpened(new RoutedEventArgs());
};
SizeChanged += OnContextMenuOrRootVisualSizeChanged;
if (null != _rootVisual)
{
_rootVisual.SizeChanged += OnContextMenuOrRootVisualSizeChanged;
}
if (ReadLocalValue(DataContextProperty) == DependencyProperty.UnsetValue)
{
DependencyObject dataContextSource = Owner ?? _rootVisual;
SetBinding(DataContextProperty, new Binding("DataContext") { Source = dataContextSource });
}
_popup.IsOpen = true;
Focus();
// Update IsOpen
_settingIsOpen = true;
IsOpen = true;
_settingIsOpen = false;
}