问题描述
我想实现一个类似于以下设计的弹出样式:
I would like to implement a popup style that looks like the following design:
灰色方框表示UIElement
,单击该弹出框可显示弹出窗口.弹出样式只是带有箭头的边框(容易部分),该箭头指向目标元素的中心(困难部分).对齐方式也很重要,当将控件放置在窗口的右侧时,弹出窗口应与右侧对齐,否则应与左侧对齐.
The gray square represents the UIElement
that shows the popup when it is clicked. The popup style is just a border (the easy part) with an arrow head that points to the center of the target element (the hard part). Also the aligment is important, when a control is placed on the right part of the window, the popup should be aligned to the right, otherwise to the left.
是否有示例或一些文档指示我如何进行?
Is there an example or some documentation that instruct me how to proceed?
推荐答案
我使用了 CustomPopupPlacementCallback委托.我什至考虑过您箭头的垂直移动.因此,现在在下面的示例中,箭头向左/向右,向上/向下移动.
I have used CustomPopupPlacementCallback Delegate . I have even considered vertical shifting of your arrow. So, now in this example below, arrow shifts left/right, up/down.
一个人可以原样使用此示例.
One can use this sample as it is.
Window1.xaml
Window1.xaml
<Window ...>
<Grid>
<Button Click="Btn_Click" Width="110" Height="25" Content="Button" HorizontalAlignment="Left" Margin="437,26,0,0" VerticalAlignment="Top"/>
<Button Click="Btn_Click" Content="Button" HorizontalAlignment="Left" Margin="10,90,0,0" VerticalAlignment="Top" Width="75"/>
<Button Click="Btn_Click" Content="Button" HorizontalAlignment="Left" Margin="139,146,0,0" VerticalAlignment="Top" Width="75"/>
<Button Click="Btn_Click" Content="Button" HorizontalAlignment="Left" Margin="180,0,0,0" VerticalAlignment="Top" Width="74"/>
<Button Click="Btn_Click" Content="Button" HorizontalAlignment="Left" Margin="224,333,0,0" VerticalAlignment="Top" Width="76"/>
<Button Click="Btn_Click" Content="Button" HorizontalAlignment="Right" VerticalAlignment="Top" Width="75"/>
<Button Click="Btn_Click" Content="Button" HorizontalAlignment="Left" VerticalAlignment="Bottom" Width="75" />
<Button Click="Btn_Click" Content="Button" HorizontalAlignment="Right" VerticalAlignment="Bottom" Width="75" />
<Button Click="Btn_Click" Content="Button" HorizontalAlignment="Left" VerticalAlignment="Top" Width="75" />
<Popup x:Name="Popup1" Placement="Custom" StaysOpen="False" Opened="Popup1_Opened">
<Grid x:Name="Grd" Width="300" Height="100" Background="AliceBlue">
<Canvas x:Name="Cnv">
<Path x:Name="TopArrow" Canvas.Left="50" Canvas.Top="25" Margin="5" Data="M0,0 L-5,-5 L-10,0 z" Fill="Black" Stroke="Black" StrokeThickness="2"/>
<TextBlock Canvas.Top="35" FontSize="18" x:Name="Tb1"/>
</Canvas>
</Grid>
</Popup>
</Grid>
</Window>
Window1.xaml.cs
Window1.xaml.cs
using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
using System.Windows.Shapes;
namespace ...
{
/// <summary>
/// Interaction logic for Window1.xaml
/// </summary>
public partial class Window1 : Window
{
public Window1()
{
InitializeComponent();
Popup1.CustomPopupPlacementCallback =
new CustomPopupPlacementCallback(placePopup);
}
public CustomPopupPlacement[] placePopup(Size popupSize,
Size targetSize,
Point offset)
{
CustomPopupPlacement placement2 =
new CustomPopupPlacement(new Point(-(popupSize.Width - targetSize.Width / 2), targetSize.Height), PopupPrimaryAxis.Vertical);
CustomPopupPlacement placement1 =
new CustomPopupPlacement(new Point(targetSize.Width / 2, targetSize.Height), PopupPrimaryAxis.Vertical);
CustomPopupPlacement placement3 =
new CustomPopupPlacement(new Point(targetSize.Width/2, -popupSize.Height), PopupPrimaryAxis.Horizontal);
CustomPopupPlacement placement4 =
new CustomPopupPlacement(new Point(-(popupSize.Width - targetSize.Width/2), -popupSize.Height), PopupPrimaryAxis.Horizontal);
CustomPopupPlacement[] ttplaces =
new CustomPopupPlacement[] { placement1, placement2, placement3, placement4 };
return ttplaces;
}
private void Btn_Click(object sender, RoutedEventArgs e)
{
Popup1.PlacementTarget = sender as Button;
Popup1.IsOpen = true;
}
private void Popup1_Opened(object sender, EventArgs e)
{
Path arrow = ((Path)Popup1.FindName("TopArrow"));
Grid grd = ((Grid)Popup1.FindName("Grd"));
UIElement elem = (UIElement)Popup1.PlacementTarget;
Point elem_pos_lefttop = elem.PointToScreen(new Point(0, 0));
Point popup_pos_lefttop = grd.PointToScreen(new Point(0, 0));
if ( (elem_pos_lefttop.Y < popup_pos_lefttop.Y )
&&
((elem_pos_lefttop.X > popup_pos_lefttop.X))
)
{
Canvas.SetLeft(arrow, 280);
Canvas.SetTop(arrow, 25);
}
if ((elem_pos_lefttop.Y < popup_pos_lefttop.Y)
&&
((elem_pos_lefttop.X < popup_pos_lefttop.X))
)
{
Canvas.SetLeft(arrow, 30);
Canvas.SetTop(arrow, 25);
}
if ((elem_pos_lefttop.Y > popup_pos_lefttop.Y)
&&
((elem_pos_lefttop.X > popup_pos_lefttop.X))
)
{
Canvas.SetLeft(arrow, 280);
Canvas.SetTop(arrow, 90);
}
if ((elem_pos_lefttop.Y > popup_pos_lefttop.Y)
&&
((elem_pos_lefttop.X < popup_pos_lefttop.X))
)
{
Canvas.SetLeft(arrow, 30);
Canvas.SetTop(arrow, 90);
}
Tb1.Text = String.Format("Element = {0} \r\n Popup = {1}", elem_pos_lefttop, popup_pos_lefttop);
}
}
}
请告知这是否可以解决您的问题.
Please tell if this solves your issue.
这篇关于带有箭头样式的WPF弹出窗口的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!