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.
Basically, to keep it on top you just set the lose focus event to make it go back to top.
First, in window. xaml we will define a button and pass the values to it's Click property that is the name of the event generated on the clicking of the Show popup button. Here two grids are used, one inside the other. The other grid contains the ellipse with color filled and a button showing the Hide text on it.
Advertisements. Popup is a control that displays content on top of existing content, within the bounds of the application window. It is a temporary display on other content.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With