当前位置: 首页 > 知识库问答 >
问题:

为什么自定义用户控件上的标签会引发mouseleave事件?

曾航
2023-03-14

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

以下是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>

以及codebehind中的构造函数/事件函数:

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];
        }
    }

基本上,当鼠标进入控件时,椭圆的笔划应该会改变,除非井经历了一次操作,使其处于“池”状态。

当鼠标进入控件时,它的响应和我预期的完全一样:MouseEnter事件处理程序会触发。但是,当用户将鼠标移动到控件内的一个标签上时,MouseLeve事件会触发。因此,即使标签表面上是控件的一部分,下面的图片显示了我所说的。打印屏幕删除了光标,但我用蓝点表示光标的位置:

正确响应:

现在它似乎认为鼠标已经离开了控制:

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

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

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

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


共有2个答案

谢嘉
2023-03-14

好吧,见鬼,在对它进行了大量搜索之后,发现问题确实包含在另一个控件中。我有另一个UserControl类,EmptyWellControl,它有一个标签。标签中的文本位置是使用标签高度属性计算的,这导致了一个无意义的值,使得标签垂直延伸到窗口的尺寸之外。该标签没有背景,但却干扰了其路径交叉的控件。由于空井和样品井均布置在同一网格上,因此每个SampleWellControl都受到这些标签的影响。

太叔正文
2023-03-14

使用的组合

IsHitTestVisible="False"

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

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

然后你的容器,其中有事件,给一个背景

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

(我也想发表评论,但名声太蠢了)

 类似资料:
  • 问题内容: 我找到了一个网站,该网站提供了将自定义标签添加到html的指南,就像人们制作新的HTML5标签一样。我必须承认,我认为添加我自己的标签,“扫描”代码并查找所需内容会更好。但是我发现的每个网站,人们都说这不好。…但是为什么不好呢? 带有类的示例html: 在这里,我可以使用自定义标签进行操作,我认为这很容易找到解决方法,所以为什么不这样做: 问题答案: 自定义标签不是邪恶的 请考虑一下:

  • 我有一个SVG,里面有更多SVG,其中包含数量可变的rect元素,所有这些都是从数据对象生成的。以下是一般层次结构: 我已将mouseenter/mouseleave事件绑定到

  • 我希望有人能向我解释一下为什么SceneBuilder在导入自定义控件时如此温和。 以一个相对简单的自定义控件为例(仅作为示例): 然后你有控制器类在这里: 这工作得很好。.jar编译得很好,SceneBuilder读取的.jar很好,它导入的控件也很好,这很好。 让我恼火的是,它需要两个独立的类来完成,这没什么大不了的,除了我觉得只用一个类就可以做到这一点。 我现在有了上面的方法,但是我尝试了另

  • 因此,我有一个#container div的简单设置,其中包含一个#field div。我还有一个不可见的#悬停范围,它跟随鼠标移动(居中)并在#field上悬停时可见。 HTML: JS公司: 当我在场地上悬停时,只要我移动鼠标,它就会触发无数的mouseenter和mouseleave(预期的mousemove)事件。这似乎是因为#悬停范围以鼠标为中心,每次移动鼠标时,我都会离开#字段并输入#

  • 我已经阅读了Github Actions留档,无法弄清楚为什么当我发布新版本时,GitHub Action工作流会被几乎同时的和事件触发。换句话说,我的工作流yaml文件是这样开始的,指定它应该为推送和发布事件运行: 当我发布一个新版本(标签)时,我希望它执行一次。然而,我看到两个事件几乎同时触发(间隔约5-10秒): 现在,事件确实触发了我的存储库的,但唯一正在更新的文件是我的文件。事件的定义没

  • 我知道,当使用WebView加载第三方内容时,在安全性方面有很多事情需要考虑,因为WebView在您的流程中运行。Chrome自定义选项卡在哪个过程中工作?您的应用程序是否存在类似的安全问题?