【问题标题】:Why do the labels on my custom user control cause the mouseleave event to fire?为什么我的自定义用户控件上的标签会触发 mouseleave 事件?
【发布时间】:2014-07-31 19:18:04
【问题描述】:

我编写了一个自定义 WPF 用户控件。这是一个带有Grid 的正方形,名为Base。在该网格中,我添加了一个椭圆和两个标签(volumelocation),其中填充了从对象属性中提取的文本,该对象在控件实例化时作为参数给出。

这是 XAML:

<UserControl x:Class="EasyHyb.SampleWellControl"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             mc:Ignorable="d" 
             d:DesignHeight="100" d:DesignWidth="100">
    <Grid x:Name="Base">
    </Grid>
</UserControl>

以及代码隐藏中的构造函数/事件函数:

public SampleWellControl(int size, SourceSample sample)
        {
            InitializeComponent();
            this.sample = sample;
            this.Width = this.Height = size;
            this.selected = SelectionStatus.Unselected;

            double spacing = size / 4;

            volume = new Label();
            location = new Label();

            volume.Content = String.Format("{0:0.00}", sample.volume);
            location.Content = sample.well.well;

            volume.HorizontalAlignment = location.HorizontalAlignment = System.Windows.HorizontalAlignment.Center;
            volume.FontFamily = location.FontFamily = new System.Windows.Media.FontFamily("Meiryo UI");
            volume.FontWeight = location.FontWeight = FontWeights.Bold;
            volume.Background = location.Background = Base.Background = this.Background = Brushes.Transparent;
            volume.Margin = new Thickness(0, spacing, 0, 0);
            location.Margin = new Thickness(0, spacing * 2, 0, 0);

            well = new Ellipse();
            well.Width = well.Height = this.Width;
            well.StrokeThickness = 3;

            Base.Children.Add(well);
            Base.Children.Add(volume);
            Base.Children.Add(location);

            this.MouseEnter += SampleWellControl_MouseEnter;
            this.MouseLeave += SampleWellControl_MouseLeave;
            this.MouseUp += SampleWellControl_MouseUp;

            this.Cursor = Cursors.Hand;

            UpdateFillAndStroke();
        }

    void SampleWellControl_MouseLeave(object sender, MouseEventArgs e)
    {
        RevertWell();
    }

    void SampleWellControl_MouseEnter(object sender, MouseEventArgs e)
    {
        HighlightWell();
    }

    public void HighlightWell()
    {
        if (this.selected == SelectionStatus.Pooled)
        {
            return;
        }
        if (this.selected == SelectionStatus.Unselected)
        {
            this.well.Stroke = this.strokes[SelectionStatus.Selected];
        }
        else
        {
            this.well.Stroke = this.strokes[SelectionStatus.Unselected];
        }
    }

    public void RevertWell()
    {
        if (this.selected == SelectionStatus.Pooled)
        {
            return;
        }
        if (this.selected == SelectionStatus.Unselected)
        {
            this.well.Stroke = this.strokes[SelectionStatus.Unselected];
        }
        else
        {
            this.well.Stroke = this.strokes[SelectionStatus.Selected];
        }
    }

基本上,当鼠标进入控件时,椭圆的笔划应该会发生变化,除非井经过操作使其处于“Pooled”状态。

当鼠标进入控件时,它的响应完全符合我的预期:MouseEnter 事件处理程序触发。但是,当用户将鼠标移到控件内的某个标签上时,会触发 MouseLeave 事件。所以即使标签表面上是控件的一部分下面的图片显示了我在说什么。 Print Screen 删除了光标,但我用蓝点表示光标所在的位置:

正确回应:

现在似乎认为鼠标离开了控件:

我尝试将 MouseEnter 和 MouseLeave 事件处理程序添加到标签,但它们不会触发。当鼠标悬停在标签上时,光标也会从手形变为指针。在另一个类中实例化后,我尝试将 MouseEnter 和 MouseLeave 事件处理程序添加到控件。我为网格、控件和标签添加了透明背景,但这也没有任何区别。

我还检查了我的 MouseLeave 事件处理程序以查看鼠标是否在控件上方,并且似乎控件没有将光标检测为在控件本身上方:

if(!this.IsMouseOver)
{
    RevertWell();
}
//also tried IsMouseDirectlyOver

我希望MouseLeave 仅在光标退出控件的方形边界时触发。如何在保留标签的同时做到这一点?

【问题讨论】:

  • 我不确定您在 SampleWellControl_MouseEnter 方法、SampleWellControl_MouseLeave 方法或 UpdateFillAndStroke 方法中在做什么,但是当我实现您的代码时,它按预期执行。您可能想查看未列出代码的 3 种方法之一。我怀疑问题出在其中一个人身上。
  • @Stewbob 谢谢!我相应地编辑了帖子。您是说当您将鼠标悬停在标签上时 MouseLeave 不会触发?
  • 正确。当我将鼠标悬停在标签上时,MouseLeave not 不会触发。
  • @DeeDee 有什么理由不关注 XAML 中的事件吗?您是否尝试过让 Grid 的 IsHitTestVisible=False?
  • @NETscape 我没有真正的理由在代码隐藏中这样做。我尝试通过 XAML 连接处理程序,但这并没有改变任何东西。我也尝试添加 IsHitTestVisible,但这也没有改变任何东西。很好的建议,谢谢!

标签: c# wpf events


【解决方案1】:

结合使用

IsHitTestVisible="False"

在您添加到 Base 的所有对象上:

volume = new Label();
volume.IsHitTestVisible="False";

然后你的容器有事件,给背景

<Grid x:Name="Base" Background="White">

(我也想评论,但声誉很愚蠢)

【讨论】:

  • 我已经在上面的代码中为Base Grid 提供了透明背景,但我会尝试第一个建议。谢谢!
  • 透明的行为与其他颜色不同。如果这不起作用,请尝试删除其他区域的透明度。
  • 嗯,我很早就添加了透明度作为故障排除步骤。我尝试了您的“isHitTestVisible”建议,但没有奏效,但这是个好主意。在控制之外,这里肯定有其他东西在起作用。
【解决方案2】:

哎呀,经过大量搜索后发现问题确实包含在另一个控件中。我有另一个UserControl 类,EmptyWellControl,它有一个Label。标签内的文本位置是使用LabelHeight 属性计算的,这导致了一个无意义的值,使标签垂直延伸远远超出了窗口的尺寸。标签没有背景,但仍然干扰了它穿过的控件。由于空井和样品井都布置在同一个网格上,因此每个SampleWellControl 都会受到这些标签的影响。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-10-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-10-01
    相关资源
    最近更新 更多