wpf 弹出窗口在 PlacementTarget 的中心和底部对齐
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/11835237/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Popup aligned on center and bottom of PlacementTarget
提问by sohum
I'm basically trying to implement a popup on a button hover. When a user is hovered over the button I want the popup to appear. When they're not, I want only the label to appear. It is kinda like a tooltip except that I don't want the Popup going away after some amount of time passes. I kinda have it working using a ControlTemplate on the button with two caveats:
我基本上是在尝试在按钮悬停时实现弹出窗口。当用户将鼠标悬停在按钮上时,我希望弹出窗口出现。当它们不是时,我只想显示标签。它有点像工具提示,只是我不希望弹出窗口在一段时间后消失。我有点让它在按钮上使用 ControlTemplate 工作,但有两个警告:
When I hover over the area below the button, the screen flickers between the popup and a label.- I want the Popup to be aligned bottom and center.
当我将鼠标悬停在按钮下方的区域上时,屏幕会在弹出窗口和标签之间闪烁。- 我希望弹出窗口底部和中心对齐。
Xaml Code:
Xml代码:
<Window>
<Window.Resources>
<Style x:Key="LabelStyle" TargetType="Label">
<Setter Property="Margin" Value="0, 0, 0, 5" />
<Setter Property="Width" Value="58" />
<Setter Property="Height" Value="28" />
<Setter Property="Padding" Value="1, 0, 1, 0" />
</Style>
<ControlTemplate x:Key="ButtonControlTemplate" TargetType="Button">
<StackPanel>
<Button Width="48" Height="48" Background="White" Name="ItemButton">
<ContentPresenter Content="{TemplateBinding Property=ContentControl.Content}" />
</Button>
<Label Style="{StaticResource LabelStyle}" VerticalContentAlignment="Top" HorizontalContentAlignment="Center" Name="ItemLabel">
<TextBlock TextWrapping="Wrap" TextAlignment="Center" FontSize="11" LineHeight="13" LineStackingStrategy="BlockLineHeight">
Hello World!
</TextBlock>
</Label>
<Popup Name="ItemPopup" Placement="Bottom" PlacementTarget="{Binding ElementName=ItemButton}">
<TextBlock Background="Red">Hello World!</TextBlock>
</Popup>
</StackPanel>
<ControlTemplate.Triggers>
<Trigger SourceName="ItemButton" Property="IsMouseOver" Value="True">
<Setter TargetName="ItemLabel" Property="Visibility" Value="Hidden" />
<Setter TargetName="ItemPopup" Property="IsOpen" Value="True" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Window.Resources>
<StackPanel>
<Button Background="Green" Template="{StaticResource ButtonControlTemplate}">
<Image Source="http://leduc998.files.wordpress.com/2010/10/msft_logo.jpg" />
</Button>
</StackPanel>
</Window>
Edit:Fixed the flicker issue. Just need the placement of the Popup to be bottom and center.
编辑:修复了闪烁问题。只需要将 Popup 放置在底部和中心即可。
采纳答案by sohum
I ended up having to write a converter that moved it down based on the height of the popup and the placement target.
我最终不得不编写一个转换器,根据弹出窗口的高度和放置目标将其向下移动。
Use a multibinding like this to pass the info into my converter for VerticalOffset:
使用这样的多重绑定将信息传递到我的 VerticalOffset 转换器中:
<MultiBinding Converter="{StaticResource PopupVerticalAligner}">
<Binding RelativeSource="{RelativeSource Self}" Path="PlacementTarget.ActualHeight" />
<Binding RelativeSource="{RelativeSource Self}" Path="ActualHeight" />
</MultiBinding>
回答by DharmaTurtle
Adding to sohum's answer, here's how I got my ListView-Popup bottom centered under a ToggleButton. It correctly horizontaly offsets depending on how wide the listview is. I also left in bits and pieces that give the togglebutton intuitive behavior, like clicking the togglebutton again to hide the popup.
添加到 sohum 的答案,这里是我如何让我的 ListView-Popup 底部在 ToggleButton 下居中。它根据列表视图的宽度正确地水平偏移。我还留下了一些零碎的部分,使切换按钮具有直观的行为,例如再次单击切换按钮以隐藏弹出窗口。
<ToggleButton x:Name="ParentToggleButton" IsChecked="{Binding ToggleButtonStatus}" IsHitTestVisible="{Binding ElementName=ToggledPopup, Path=IsOpen, Converter={StaticResource BoolToInvertedBoolConverter}}" >
<ToggleButton.Content>...</ToggleButton.Content>
</ToggleButton>
<Popup PlacementTarget="{Binding ElementName=ParentToggleButton}" Placement="Bottom" StaysOpen="False" IsOpen="{Binding ToggleButtonStatus}" x:Name="ToggledPopup">
<Popup.HorizontalOffset>
<MultiBinding Converter="{StaticResource CenterToolTipConverter}">
<Binding RelativeSource="{RelativeSource Self}" Path="PlacementTarget.ActualWidth"/>
<Binding ElementName="INeedYourWidth" Path="ActualWidth"/>
</MultiBinding>
</Popup.HorizontalOffset>
<ListView x:Name="INeedYourWidth" ItemsSource="{Binding ItemsSource}" >
<ListView.ItemTemplate>
<DataTemplate>...</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</Popup>
BoolToInvertedBoolConverter returns true if false and false if true (to allow the popup to collapse when the user tries to untoggle it) and CenterToolTipConverter can be found in sohum's link.
BoolToInvertedBoolConverter 如果为 false 则返回 true ,如果为 true 则返回 false (以允许当用户尝试取消切换时弹出窗口折叠)并且 CenterToolTipConverter 可以在 sohum 的链接中找到。
回答by dotNET
Much better is to put your PlacementTargetcontrol inside a Gridand make your Popupcontrol a child of the same Gridwhile keeping Placement=Bottom. This will show your Popupbottom-centered under the PlacementTarget control. No converters, no styles, plain simple XAML.
更好的是将您的PlacementTarget控件放在 a 中Grid,并使您的Popup控件成为相同的子控件,Grid同时保持Placement=Bottom. 这将Popup在 PlacementTarget 控件下显示您的底部居中。没有转换器,没有样式,简单的 XAML。
回答by LueTm
Have you tried the MouseEnter event? Then you can open the popup on a DispatcherTimer and then close it again.
您是否尝试过 MouseEnter 事件?然后您可以在 DispatcherTimer 上打开弹出窗口,然后再次关闭它。

