UWP - PointerEntered/PointerExited 模拟鼠标悬停在网格行上
UWP - PointerEntered/PointerExited to simulate mousehover on grid rows
我已经检查过了。但我面临着一个不同的 "flickering" 问题。
我在 ScrollViewer 中有一个 Grid,它是 PivotItem 控件的子控件。网格一开始是空的,然后以编程方式填充。
<PivotItem>
<ScrollViewer x:Name="MyScrollBar" >
<Grid Name="MyGrid">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"></RowDefinition>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"></ColumnDefinition>
<ColumnDefinition Width="*"></ColumnDefinition>
<ColumnDefinition Width="*"></ColumnDefinition>
</Grid.ColumnDefinitions>
</Grid>
</ScrollViewer>
</PivotItem>
然后每列都填充了 3 个 TextBlock。
我的目标是在将鼠标悬停在一行(而不是单个 TextBlock)上时显示带有其他详细信息的 Flyout。为此,我为每一行定义了一个 ColumnSpan 为 3 的附加透明 Rectangle,并将其添加为每一行的最后一个子项。然后我给它一个 Flyout 如下:
Rectangle rect = new Rectangle();
rect.Opacity = 0;
rect.SetValue(Grid.RowProperty, r);
rect.SetValue(Grid.ColumnSpanProperty, 3);
Flyout fl = new Flyout();
Grid flGrid = new Grid();
TextBlock flTb1 = new TextBlock();
flTb1.Text = details.Name;
flGrid.Children.Add(flTb1);
fl.Content = flGrid;
rect.SetValue(FlyoutBase.AttachedFlyoutProperty, fl);
rect.PointerEntered += Rect_PointerEntered;
rect.PointerExited += Rect_PointerExited;
rect.Margin = new Thickness(2);
这里是 PointerEntered 和 PointerExited 事件处理程序:
private void Rect_PointerEntered(object sender, PointerRoutedEventArgs e)
{
((Flyout)(((Rectangle)sender).GetValue(FlyoutBase.AttachedFlyoutProperty))).ShowAt((Rectangle)sender);
}
private void Rect_PointerExited(object sender, PointerRoutedEventArgs e)
{
((Flyout)(((Rectangle)sender).GetValue(FlyoutBase.AttachedFlyoutProperty))).Hide();
}
当指针进入网格行的命中区域时,弹出按钮突然出现
并消失。每当指针移动时,即使在同一行上也是如此(我不希望在将指针移动到同一行上时 Flyout 消失)。结果是一个闪烁的弹出窗口。在我看来,PointerEntered/PointerExited 事件都在悬停的任何时候触发。
我已经尝试过的:
- 仅处理 PointerEntered(我知道这不是最佳做法,但我试过了)
- 将 PointerEntered.Handled 设置为 false(我认为可能是网格中的其他控件影响了行为)
- 仅处理 PointerMoved
- 存储 "hovered" 和 "hovering" 矩形以识别指针何时位于 same/another 行上方
- 很多我什至不记得的其他尝试...总是得到相同的闪烁结果。
谁能指出我正确的方向?提前致谢!
It seemes to me that the PointerEntered/PointerExited events are both fired at any point hovered.
似乎一旦Flyout
出现,即使鼠标没有离开命中测试区域,PointerExited
也会被触发。如果没有 Flyout
,Pointer
事件可以像您想象的那样工作,为此您可以测试 official sample.
Handle the PointerEntered only (I know this is not best practice, but I tried)
这种方法应该可行,因为如果没有 PointerExited
事件,Flyout
将不会被隐藏。我还测试了 Flyout
直到点击另一个 space 才会消失。但正如你所说,这可能不是一个好的做法。
private void Rect_PointerEntered(object sender, PointerRoutedEventArgs e)
{
((Flyout)(((Rectangle)sender).GetValue(FlyoutBase.AttachedFlyoutProperty))).ShowAt((Rectangle)sender);
}
private void Rect_PointerExited(object sender, PointerRoutedEventArgs e)
{
//((Flyout)(((Rectangle)sender).GetValue(FlyoutBase.AttachedFlyoutProperty))).Hide();
}
您可以尝试使用另一种方法 ToolTip
。您甚至不需要 Pointer
事件,当您悬停该行时,它会显示,当您移出时它会消失。它不会闪烁。虽然过一段时间它会消失,但我觉得你展示细节就够了。
Rectangle rect = new Rectangle();
rect.Opacity = 0.3;
rect.SetValue(Grid.RowProperty, r);
rect.SetValue(Grid.ColumnSpanProperty, 3);
rect.Fill = new SolidColorBrush(Colors.Azure);
Grid flGrid = new Grid();
TextBlock flTb1 = new TextBlock();
flTb1.Text = "testname"+r;
flGrid.Children.Add(flTb1);
rect.SetValue(ToolTipService.ToolTipProperty, flGrid);
rect.Margin = new Thickness(2);
MyGrid.Children.Add(rect);
正如@Sunteen 在之前的回答中指出的那样,弹出窗口将激活 PointerExited 事件。您可以使用 TeachingTip 控件而不是弹出控件。 TeachingTip 控件不会触发 PointerExited,因此您可以获得悬停效果。请注意,您可能需要添加 TeachingTip 控件。参见
<xmlns:controls="using:Microsoft.UI.Xaml.Controls">
<Image
Name="draggable_image"
PointerEntered="Draggable_image_PointerEntered"
PointerExited="Draggable_image_PointerExited"/>
<controls:TeachingTip
x:Name="IconTip"
Target="{x:Bind draggable_image}"
PreferredPlacement="Bottom"
PlacementMargin="10"/>
private void Draggable_image_PointerEntered(object sender, PointerRoutedEventArgs e)
{
//IconTip.Title = set title
//IconTip.Subtitle = set sub title;
IconTip.IsOpen = true;
}
private void Draggable_image_PointerExited(object sender, PointerRoutedEventArgs e)
{
IconTip.IsOpen = false;
}
我已经检查过了
我在 ScrollViewer 中有一个 Grid,它是 PivotItem 控件的子控件。网格一开始是空的,然后以编程方式填充。
<PivotItem>
<ScrollViewer x:Name="MyScrollBar" >
<Grid Name="MyGrid">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"></RowDefinition>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"></ColumnDefinition>
<ColumnDefinition Width="*"></ColumnDefinition>
<ColumnDefinition Width="*"></ColumnDefinition>
</Grid.ColumnDefinitions>
</Grid>
</ScrollViewer>
</PivotItem>
然后每列都填充了 3 个 TextBlock。 我的目标是在将鼠标悬停在一行(而不是单个 TextBlock)上时显示带有其他详细信息的 Flyout。为此,我为每一行定义了一个 ColumnSpan 为 3 的附加透明 Rectangle,并将其添加为每一行的最后一个子项。然后我给它一个 Flyout 如下:
Rectangle rect = new Rectangle();
rect.Opacity = 0;
rect.SetValue(Grid.RowProperty, r);
rect.SetValue(Grid.ColumnSpanProperty, 3);
Flyout fl = new Flyout();
Grid flGrid = new Grid();
TextBlock flTb1 = new TextBlock();
flTb1.Text = details.Name;
flGrid.Children.Add(flTb1);
fl.Content = flGrid;
rect.SetValue(FlyoutBase.AttachedFlyoutProperty, fl);
rect.PointerEntered += Rect_PointerEntered;
rect.PointerExited += Rect_PointerExited;
rect.Margin = new Thickness(2);
这里是 PointerEntered 和 PointerExited 事件处理程序:
private void Rect_PointerEntered(object sender, PointerRoutedEventArgs e)
{
((Flyout)(((Rectangle)sender).GetValue(FlyoutBase.AttachedFlyoutProperty))).ShowAt((Rectangle)sender);
}
private void Rect_PointerExited(object sender, PointerRoutedEventArgs e)
{
((Flyout)(((Rectangle)sender).GetValue(FlyoutBase.AttachedFlyoutProperty))).Hide();
}
当指针进入网格行的命中区域时,弹出按钮突然出现 并消失。每当指针移动时,即使在同一行上也是如此(我不希望在将指针移动到同一行上时 Flyout 消失)。结果是一个闪烁的弹出窗口。在我看来,PointerEntered/PointerExited 事件都在悬停的任何时候触发。
我已经尝试过的:
- 仅处理 PointerEntered(我知道这不是最佳做法,但我试过了)
- 将 PointerEntered.Handled 设置为 false(我认为可能是网格中的其他控件影响了行为)
- 仅处理 PointerMoved
- 存储 "hovered" 和 "hovering" 矩形以识别指针何时位于 same/another 行上方
- 很多我什至不记得的其他尝试...总是得到相同的闪烁结果。
谁能指出我正确的方向?提前致谢!
It seemes to me that the PointerEntered/PointerExited events are both fired at any point hovered.
似乎一旦Flyout
出现,即使鼠标没有离开命中测试区域,PointerExited
也会被触发。如果没有 Flyout
,Pointer
事件可以像您想象的那样工作,为此您可以测试 official sample.
Handle the PointerEntered only (I know this is not best practice, but I tried)
这种方法应该可行,因为如果没有 PointerExited
事件,Flyout
将不会被隐藏。我还测试了 Flyout
直到点击另一个 space 才会消失。但正如你所说,这可能不是一个好的做法。
private void Rect_PointerEntered(object sender, PointerRoutedEventArgs e)
{
((Flyout)(((Rectangle)sender).GetValue(FlyoutBase.AttachedFlyoutProperty))).ShowAt((Rectangle)sender);
}
private void Rect_PointerExited(object sender, PointerRoutedEventArgs e)
{
//((Flyout)(((Rectangle)sender).GetValue(FlyoutBase.AttachedFlyoutProperty))).Hide();
}
您可以尝试使用另一种方法 ToolTip
。您甚至不需要 Pointer
事件,当您悬停该行时,它会显示,当您移出时它会消失。它不会闪烁。虽然过一段时间它会消失,但我觉得你展示细节就够了。
Rectangle rect = new Rectangle();
rect.Opacity = 0.3;
rect.SetValue(Grid.RowProperty, r);
rect.SetValue(Grid.ColumnSpanProperty, 3);
rect.Fill = new SolidColorBrush(Colors.Azure);
Grid flGrid = new Grid();
TextBlock flTb1 = new TextBlock();
flTb1.Text = "testname"+r;
flGrid.Children.Add(flTb1);
rect.SetValue(ToolTipService.ToolTipProperty, flGrid);
rect.Margin = new Thickness(2);
MyGrid.Children.Add(rect);
正如@Sunteen 在之前的回答中指出的那样,弹出窗口将激活 PointerExited 事件。您可以使用 TeachingTip 控件而不是弹出控件。 TeachingTip 控件不会触发 PointerExited,因此您可以获得悬停效果。请注意,您可能需要添加 TeachingTip 控件。参见
<xmlns:controls="using:Microsoft.UI.Xaml.Controls">
<Image
Name="draggable_image"
PointerEntered="Draggable_image_PointerEntered"
PointerExited="Draggable_image_PointerExited"/>
<controls:TeachingTip
x:Name="IconTip"
Target="{x:Bind draggable_image}"
PreferredPlacement="Bottom"
PlacementMargin="10"/>
private void Draggable_image_PointerEntered(object sender, PointerRoutedEventArgs e)
{
//IconTip.Title = set title
//IconTip.Subtitle = set sub title;
IconTip.IsOpen = true;
}
private void Draggable_image_PointerExited(object sender, PointerRoutedEventArgs e)
{
IconTip.IsOpen = false;
}