Is there any way to stop a WPF Popup from repositioning itself when it goes off-screen?
I found this old question, but it didn't get a proper answer to it. Is there any way to do this? I'm willing to subclass it if necessary. Thanks.
As Andrei points out, this behavior is deep inside the Popup
control and hard to overcome. If you are willing to do some work it can be done by resizing and translating the content of the popup when it reaches the screen edges. For the purposes of the demonstration, we'll focus on the left edge of the screen.
If we have some XAML like this:
<Window ...
LocationChanged="Window_LocationChanged"
SizeChanged="Window_SizeChanged"
>
<Grid>
<Rectangle Name="rectangle1" Width="100" Height="100" Fill="Blue"/>
<Popup Name="popup1" PlacementTarget="{Binding ElementName=rectangle1}" IsOpen="True" Width="100" Height="100">
<TextBlock Background="White" TextWrapping="Wrap" Width="100" Height="100">
<TextBlock.Text>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.</TextBlock.Text>
</TextBlock>
</Popup>
</Grid>
</Window>
and code-behind like this:
private void Window_LocationChanged(object sender, EventArgs e)
{
RefreshPopupPosition();
}
private void Window_SizeChanged(object sender, SizeChangedEventArgs e)
{
RefreshPopupPosition();
}
private void RefreshPopupPosition()
{
var upperLeft = rectangle1.PointToScreen(new Point(0, 100));
var xOffset = Math.Min(0, upperLeft.X);
popup1.Width = xOffset + 100;
(popup1.Child as FrameworkElement).Margin = new Thickness(xOffset, 0, 0, 0);
popup1.HorizontalOffset += 1;
popup1.HorizontalOffset -= 1;
}
then by calculating that the Popup
would be off-screen, we can reduce the width of the content and give it a negative margin so that the portion that is on-screen is clipped to what would have appeared if the Popup
were to allow this.
This would have to be extended to deal with all four edges of the screen and the possibility of multiple screens, but it demonstrates that the approach is workable.