private static bool TryPlacePopup(Windows.Popup popup, FrameworkElement parent, FrameworkElement placementParent, FrameworkElement placementChild, PopupOrientation orientation)
{
var availableWidth = placementParent.ActualWidth;
var availableHeight = placementParent.ActualHeight;
SetActualOrientation(popup, orientation);
placementChild.Measure(new Size(availableWidth, availableHeight));
var requiredWidth = placementChild.DesiredSize.Width;
var requiredHeight = placementChild.DesiredSize.Height;
var placementTarget = GetPlacementTarget(popup) ?? parent;
var parentTransform = placementTarget.TransformToVisual(parent);
var popupLocation = parentTransform.Transform(new Point(0, 0));
switch (orientation.Placement)
{
case PopupPlacement.Top:
popupLocation.Y -= requiredHeight;
break;
case PopupPlacement.Bottom:
popupLocation.Y += placementTarget.ActualHeight;
break;
case PopupPlacement.Left:
popupLocation.X -= requiredWidth;
break;
case PopupPlacement.Right:
popupLocation.X += placementTarget.ActualWidth;
break;
}
if (orientation.Placement == PopupPlacement.Top || orientation.Placement == PopupPlacement.Bottom)
{
switch (orientation.HorizontalAlignment)
{
case PopupHorizontalAlignment.RightCenter:
popupLocation.X += ((placementTarget.ActualWidth / 2) - requiredWidth);
break;
case PopupHorizontalAlignment.Center:
popupLocation.X += ((placementTarget.ActualWidth - requiredWidth) / 2);
break;
case PopupHorizontalAlignment.LeftCenter:
popupLocation.X += (placementTarget.ActualWidth / 2);
break;
case PopupHorizontalAlignment.Right:
popupLocation.X += (placementTarget.ActualWidth - requiredWidth);
break;
}
}
if (orientation.Placement == PopupPlacement.Left || orientation.Placement == PopupPlacement.Right)
{
switch (orientation.VerticalAlignment)
{
case PopupVerticalAlignment.BottomCenter:
popupLocation.Y += ((placementTarget.ActualHeight / 2) - requiredHeight);
break;
case PopupVerticalAlignment.Center:
popupLocation.Y += ((placementTarget.ActualHeight - requiredHeight) / 2);
break;
case PopupVerticalAlignment.TopCenter:
popupLocation.Y += (placementTarget.ActualHeight / 2);
break;
case PopupVerticalAlignment.Bottom:
popupLocation.Y += (placementTarget.ActualHeight - requiredHeight);
break;
}
}
var popupLocationRelativeToPlacementParent = popupLocation;
if (parent != placementParent)
{
var placementParentTransform = placementTarget.TransformToVisual(placementParent);
popupLocationRelativeToPlacementParent = placementParentTransform.Transform(popupLocation);
}
if (popupLocationRelativeToPlacementParent.X < 0
|| popupLocationRelativeToPlacementParent.Y < 0
|| (popupLocationRelativeToPlacementParent.X + requiredWidth) > availableWidth
|| (popupLocationRelativeToPlacementParent.Y + requiredHeight) > availableHeight)
{
// not enough room
return false;
}
popup.HorizontalOffset = popupLocation.X;
popup.VerticalOffset = popupLocation.Y;
return true;
}