WPF中的“工具提示”弹出窗口闪烁问题

6
简而言之:我有一个窗口,在其中的ListBox中显示了一堆图表。当鼠标经过LineSeries的图表时,会有一条线跟随数据点(与数据点位置对齐)。在那条线附近,我通过弹出窗口展示了有关这些数据点的信息。
到目前为止还不错。问题是当我试图将鼠标移动到工具提示上时,弹出窗口开始闪烁(就像处于打开/关闭循环中一样)。我已经在弹出窗口和子元素上设置了IsHitTestVisible="False"。
作为一个临时解决方案,弹出窗口会“离开”光标的路径,如下所示:
...但这几乎是“难以理解的”。
现在的问题是:发生了什么?为什么当鼠标在其上时,弹出窗口开始闪烁。
欢迎任何反馈意见。
PS. 工具提示的XAML(它是在代码中创建的,但这里是它):
图表的DataContext被数据绑定到一个类,还实现了一些通过icommands实现的图表事件。弹出窗口是在该类的构造函数中创建的。
ppchart = New Popup() With {.AllowsTransparency = True, .IsHitTestVisible = False,.StaysOpen = True}

在MouseMoveCommand中,弹出窗口的子元素被创建:
Dim ppCont As XElement = <Grid xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                                     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                                     xmlns:sdk="http://schemas.microsoft.com/winfx/2006/xaml/presentation/sdk" IsHitTestVisible="False" VerticalAlignment="Top">
                                     <Grid.RowDefinitions>
                                         <RowDefinition Height="Auto"/>
                                         <RowDefinition Height="Auto"/>
                                     </Grid.RowDefinitions>
                                     <Rectangle Opacity="0.5" Grid.RowSpan="2" IsHitTestVisible="False" StrokeThickness="0" RadiusX="2" RadiusY="2" Fill="#FFBABABA"/>
                                     <TextBlock Text="{Binding Over, StringFormat=HH:mm}" FontSize="9" TextAlignment="Center" FontFamily="Segoe UI" IsHitTestVisible="False" Margin="1"/>
                                     <ListBox x:Name="listBox" ItemsSource="{Binding Points}" Background="{x:Null}" BorderBrush="{x:Null}" FontSize="8" Margin="1,0,1,1" Grid.Row="1" IsHitTestVisible="False" IsTextSearchEnabled="False" HorizontalAlignment="Stretch">
                                         <ListBox.ItemContainerStyle>
                                             <Style TargetType="{x:Type ListBoxItem}">
                                                 <Setter Property="Background" Value="Transparent"/>
                                                 <Setter Property="HorizontalContentAlignment" Value="{Binding HorizontalContentAlignment, RelativeSource={RelativeSource AncestorType={x:Type ItemsControl}}}"/>
                                                 <Setter Property="VerticalContentAlignment" Value="{Binding VerticalContentAlignment, RelativeSource={RelativeSource AncestorType={x:Type ItemsControl}}}"/>
                                                 <Setter Property="Padding" Value="0"/>
                                                 <Setter Property="IsHitTestVisible" Value="False"/>
                                             </Style>
                                         </ListBox.ItemContainerStyle>
                                         <ListBox.ItemTemplate>
                                             <DataTemplate>
                                                 <Grid IsHitTestVisible="False">
                                                     <Grid.ColumnDefinitions>
                                                         <ColumnDefinition Width="Auto"/>
                                                         <ColumnDefinition Width="Auto"/>
                                                         <ColumnDefinition Width="Auto"/>
                                                     </Grid.ColumnDefinitions>
                                                     <Rectangle Fill="{Binding Culoare}" Width="3" HorizontalAlignment="Left" Margin="1" IsHitTestVisible="False"/>
                                                     <TextBlock Text="{Binding Operation}" HorizontalAlignment="Stretch" IsHitTestVisible="False" Grid.ColumnSpan="1" Grid.Column="1"/>
                                                     <TextBlock Text="{Binding points.Value}" HorizontalAlignment="Stretch" Grid.Column="2" TextAlignment="Right" IsHitTestVisible="False"/>
                                                 </Grid>
                                             </DataTemplate>
                                         </ListBox.ItemTemplate>
                                     </ListBox>
                                 </Grid>

        ppchart.Effect = New Effects.DropShadowEffect() With {.Opacity = 0.5, .BlurRadius = 5, .Direction = 80, .Color = Colors.Black}
        ppchart.Child = CType(XamlReader.Load(New XmlTextReader(New StringReader(ppCont.ToString))), UIElement)

重新编辑:这是它的外观。

在此输入图像描述


可以发布用于工具提示的XAML吗? - Dennis
你为什么要设置IsHitTestVisible?你试过不设置吗? - Kendall Frey
第一次尝试时我根本没有进行设置,结果它还是闪烁了... - Radu C
你在触发工具提示的哪个事件? - Dennis
图表的MouseMove事件绑定到一个命令。在该命令中,我创建了弹出窗口的子级,创建了它的数据上下文,并设置PopUp.IsOpen="True"... - Radu C
2个回答

2

我在使用 MouseEnterMouseLeave 事件时,也遇到了类似的问题。在 WPF 中,MouseEnter 事件有一种奇怪的行为,不知道是否是一个 bug。当你从上方进入考虑的项目时会出现闪烁。从任何其他方向进入该项都可以得到平滑的弹出窗口。因此,为了避免这种情况,我删除了:

AllowsTransparency = True

部分。

编辑:

虽然我仍然无法找到完美的解决方案,但我发现这实际上并不是 Scott Hanselman 在这里所描述的 bug。

然而,我无法将问题与自己的问题进行比较和解决。无论如何,为了拥有动画特效,我想出了一个解决方案,它至少可以通过检查鼠标的当前位置来减少额外的 Popup 控件的打开或关闭。我定义了一个变量。

Point currPoint = new Point();

然后在MouseEnter事件或处理程序中:

   ListViewItem listViewItem = e.Source as ListViewItem;           
        if(currPoint!=e.GetPosition(listViewItem))
            compToStrategyVM.OpenPopup(listViewItem, listViewPopup);

同样的,在鼠标离开事件或处理程序中:
ListViewItem listViewItem = e.Source as ListViewItem;
        if (currPoint != e.GetPosition(listViewItem))
            compToStrategyVM.ClosePopup(listViewPopup);

这里的compToStrategyVM指的是我的ViewModel,listViewPopup指的是弹出控件的名称。虽然问题仍然存在,但通过这种方法,闪烁效果已经减少到相当大的程度。


唯一的缺点是您无法使用弹出动画功能,该功能需要将上述变量设置为“true”。 - sm2mafaz

0

阅读评论后,我认为您正在使用错误的事件;MouseMove事件将不断触发,并且每次弹出窗口都会显示/隐藏或闪烁。

您应该使用MouseEnterMouseLeave事件。


我已经尝试过了,但我必须检查鼠标悬停的数据点值是否已更改(现在您会建议将其附加到数据点的 MouseEnterMouseLeave,但由于它是一个 LineSeries,因此我将数据点的宽度/高度设置为0,只需要线条。无论如何,在 MouseMove 中,我在“重新打开”弹出窗口之前检查值是否不同... - Radu C
有趣的事情。当鼠标悬停在工具提示上时,会触发 ChartMouseLeave 事件(我在其中设置了 popup.IsOpen="False")... - Radu C
你正在使用哪个图表中间件? - Dennis
@RaduC:谢谢,但我并不觉得我“赚到”了它。今天早上我检查了一下我的工具提示实现,发现我使用了MouseLeaveEventMouseMoveEvent,以便重复使用现有的Popup。也许闪烁是由于您的输入事件重新创建了Popup引起的。 - Dennis
没错 @Dennis。但是我很好奇,为什么当鼠标悬停在“PopUp”上并且您处理底层的“UIElement”的“MouseLeaveEvent”时,后者的事件会被触发... - Radu C
显示剩余2条评论

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