Есть два подхода.
Вариант 1
Вы можете разместить всплывающее окно через его свойства HorizontalOffset и VerticalOffset. Вам просто нужно выяснить, какие значения установить их. Как это: -
private void Button_Click(object sender, RoutedEventArgs e)
{
Popup popup = new Popup();
Button b = (Button)sender;
GeneralTransform gt = b.TransformToVisual(Application.Current.RootVisual);
Point p = gt.Transform(new Point(0, b.ActualHeight));
popup.HorizontalOffset = p.X;
popup.VerticalOffset = p.Y;
popup.Child = new Border()
{
Child = new TextBlock() { Text = "Hello, World!" },
Background = new SolidColorBrush(Colors.Cyan)
};
}
Здесь мы используем метод TrannsformToVisual
кнопки, чтобы получить преобразование относительно корневого визуала приложения, которое имеет то же происхождение, что и всплывающее окно. Используя фактическую высоту кнопок, мы можем получить точку в левом нижнем углу кнопки.
Вариант 2
Альтернативой является размещение всплывающего окна в макете.
<StackPanel>
<Button Content="Click Me" Click="Button_Click" />
<Popup x:Name="popup" />
<TextBlock Text="This text will be occluded when the popup is open" />
</StackPanel>
код: -
private void Button_Click(object sender, RoutedEventArgs e)
{
popup.Child = new Border()
{
Child = new TextBlock() { Text = "Hello, World!" },
Background = new SolidColorBrush(Colors.Cyan)
};
popup.IsOpen = !popup.IsOpen;
}
В этом подходе источник всплывающего окна размещается системой макетов, в этом случае мы использовали StackPanel
, поэтому всплывающее окно размещается непосредственно под кнопкой. Однако всплывающее окно не занимает места в макете, поэтому текстовое поле появляется сразу под кнопкой.