如何在应用程序的右下角显示WPF弹出窗口?

8
我正在使用WPF弹出控件。我希望它出现在我的应用程序窗口内,锚定在窗口的右下角。弹出窗口的实际高度和宽度将根据显示的消息而变化。
如果有关系的话,弹出窗口的内容是一个边框,包裹着一个StackPanel,其中包含多个TextBlock。
感谢任何帮助。
4个回答

11

使用 PlacementTarget,Placement=Left,Horizontal/VerticalOffset。

<Popup IsOpen="{Binding ElementName=togglebutton, Path=IsChecked, Mode=TwoWay}"
       PlacementTarget="{Binding ElementName=togglebutton}"
       Placement="Left"
       HorizontalOffset="{Binding ActualWidth, ElementName=togglebutton}"
       VerticalOffset="{Binding ActualHeight, ElementName=togglebutton}">

2
请注意,Placement="Left/Right" 不是绝对的真理。如果用户使用触摸屏,他们的“惯用手”设置可能会更改这一点。如果我在我的计算机上设置为右撇子,则会反转所有左/右值,而左撇子则可以正确使用放置值。似乎 CustomPopupPlacementCallback 是确保准确的方法。 - Fredrik C

5

我刚刚做了类似的事情,其实并不难,但需要自定义弹出窗口的位置。当你声明弹出窗口时,只需将PlacementMode属性设置为Custom,然后将CustomPopupPlacementCallback属性设置为要使用的方法即可。

this.trayPopup.CustomPopupPlacementCallback = GetPopupPlacement;

private static CustomPopupPlacement[] GetPopupPlacement(Size popupSize, Size targetSize, Point offset)
{
    var point = SystemParameters.WorkArea.BottomRight;
    point.Y = point.Y - popupSize.Height;
    return new[] { new CustomPopupPlacement(point, PopupPrimaryAxis.Horizontal) };
}

这将锚定弹出窗口到您的显示器的右下角,而不一定是窗口的右下角。 - sebingel

1

这是相当棘手的问题,没有简单的答案。

在你的问题中,你说:

弹出窗口的实际高度和宽度将根据显示的消息而变化。

你不用担心,这是 WPF Popup 控件的默认行为。

确保你想要的位置的步骤如下:

  1. 将 PlacementTarget 设置为应用程序窗口
  2. 弹出窗口将使用相对位置而不是绝对位置进行放置,因为起始位置始终是左上角。但确切的位置也是相对于应用程序边缘的,这意味着你必须使用自定义位置。

有关使用 Popup 的自定义放置的更多信息,请参见:

如何指定自定义 Popup 位置


1

我也一直在尝试做类似的事情,并更喜欢使用XAML进行操作。但是,在多个监视器上使用Placement=Left时出现了问题,因为弹出窗口会跳到另一个屏幕上,并且会偏离中心位置很远。使用Position=Relative并使用与容器对齐的绑定来调整偏移量更加可靠。

<Popup x:Name="RightPopupContainer" 
       StaysOpen="False" 
       Placement="Relative" 
       PlacementTarget="{Binding ElementName=BigContainer}" 
       Height="{Binding ElementName=BigContainer, Path=ActualHeight}"
       AllowsTransparency="True"
       PopupAnimation="Fade">
    <Popup.HorizontalOffset>
        <MultiBinding Converter="{StaticResource SubtractionConverter}">
            <MultiBinding.Bindings>
                <Binding ElementName="BigContainer" Path="ActualWidth" />
                <Binding ElementName="RightPopupContainer" Path="Child.ActualWidth" />
            </MultiBinding.Bindings>
        </MultiBinding>
    </Popup.HorizontalOffset>
</Popup>
SubtractionConverter是一个简单的多绑定转换器,它从BigContainer.ActualWidth中减去RightPopupContainer.Child.ActualWidth(弹出窗口始终为0宽,子元素具有实际尺寸)。这样可以将其精确地放置在容器边缘,并在任一容器大小更改时自动更新。
除了多重绑定,这里还有另一个执行相同结果的选项。
在包含您的弹出窗口的UserControl或Window中,在代码后台创建LayoutUpdated的事件监听器。在代码后台,您可以进行逻辑处理,例如:
private void UpdateElementLayouts(object sender, System.EventArgs e)
{
    if (RightPopupContainer?.IsOpen == true && RightPopupContainer.Child is UserControl content)
    {
        RightPopupContainer.HorizontalOffset = BigContainer.ActualWidth - content.ActualWidth;
    }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接