【问题标题】:Is there a way to simulate MouseOver in WPF?有没有办法在 WPF 中模拟 MouseOver?
【发布时间】:2011-02-23 20:38:30
【问题描述】:

我正在开发 WPF 中的链接控件,它适合 Windows UX 指南中的 text with icon links 案例。我想在某个图像右侧显示的超链接中包含一些文本。

在我的例子中,我开始使用包含 HyperlinkTextBlock,然后包含我的图像和一些文本。

<TextBlock>
    <Hyperlink>
        <Rectangle Height="16"
                   Width="16"
                   Fill="{StaticResource MyIconBrush}"
                   Stretch="UniformToFill"
                   VerticalAlignment="Center"
                   HorizontalAlignment="Left" />
        <Run>My link text</Run>
    </Hyperlink>
</TextBlock>

然而,这个问题是图像比我的文本高会产生文本与底部对齐的效果。不幸的是,我还没有找到一种方法来控制TextBlockHyperlink 内的垂直对齐方式,所以我尝试了另一种布局,其中Hyperlink 和代表我的矢量图标的矩形是分开的为了让它们正确对齐,如下所示。

<StackPanel Orientation="Horizontal">
    <Rectangle Height="16"
               Width="16"
               Fill="{StaticResource MyIconBrush}"
               Stretch="UniformToFill"
               VerticalAlignment="Center"
               HorizontalAlignment="Left" />
    <TextBlock VerticalAlignment="Center">
        <Hyperlink>My link text<Hyperlink>
    </TextBlock>
</StackPanel>

但是,问题在于,现在我的图标和我的Hyperlink 是分开的,当我将鼠标悬停在我的图标上时,我的链接没有鼠标悬停的外观,反之亦然。另外我的Hyperlink 有一个选项让我连接一个命令,但是 Rectangle 和 StackPanel 没有,所以如果我使用Hyperlink.Command,图标将不会执行命令。

所以这让我开始思考,我如何模拟给定控件的 MouseOver,例如当您实际将鼠标悬停在其关联的文本上时,您可以在框上获得 MouseOver 效果的复选框。我知道在 HTML 世界中 label element has a for 属性可用于指定它所标记的控件基本上可以满足我的要求。我还可以想象,在其他情况下,有一个标签可能会很好,当您将鼠标悬停时会显示相应的文本框,就好像鼠标在它上面一样,并且可能在单击时也将焦点赋予相应的文本框。目前,虽然我主要感兴趣的是如何在 WPF 中获取标签或类似标签的元素,以根据其 MouseOver 状态充当给定控件的代理。如果可能的话,我也想纯粹在 XAML 中执行此操作。

更新:我也尝试了以下但没有成功。我得到了我想要的外观,但图标下的链接似乎不足以获取鼠标事件。我猜只有当鼠标实际位于渲染文本上时,命中测试才有效,而不管控件的填充如何。

<Grid>
    <Rectangle Height="16"
               Width="16"
               Fill="{StaticResource MyIconBrush}"
               Stretch="UniformToFill"
               HorizontalAlignment="Left"
               VerticalAlignment="Center"
               IsHitTestVisible="False"
               Focusable="False"/>
    <TextBlock Padding="18,0,0,0"
               VerticalAlignment="Center">
        <Hyperlink>Configure additional filters...</Hyperlink>
    </TextBlock>
</Grid>

【问题讨论】:

  • 第二个 XML 块中的内容格式不正确 - &lt;Hyperlink&gt;My link text&lt;Hyperlink&gt;&lt;Hyperlink&gt; 结尾,而不是 &lt;/Hyperlink&gt;

标签: wpf mouseover hyperlink


【解决方案1】:

第一个代码是要走的路。您可以使用BaselineAlignment 控制Run 对齐。将其设置为Center,您的链接将按照您的意愿运行。

【讨论】:

  • 这确实解决了我原来与对齐有关的问题,但我注意到在以这种方式实施后,我的图标也会被加下划线,更糟糕的是,文本和图像之间的下划线被破坏了。我想我必须找到一种不同的策略,其中仍然存在基本问题,即如何在 WPF 中模拟 MouseOver。
【解决方案2】:

使用 Run 和 BaselineAlignment="Center" 将导致链接断开。只需将图像和文本块填充到这样的水平堆栈面板中即可。

<TextBlock> 
    <Hyperlink> 
        <StackPanel Orientation="Horizontal">
            <Rectangle 
                Height="16" Width="16" 
                Fill="{StaticResource MyIconBrush}" 
                Stretch="UniformToFill" VerticalAlignment="Center" HorizontalAlignment="Left" /> 
            <TextBlock 
                Text="My link text" 
                VerticalAlignment="Center"/>
        </StackPanel>
    </Hyperlink>
</TextBlock>

如果您希望控件以与默认方式不同的方式对鼠标悬停事件做出可见反应,则需要覆盖其控件模板。最简单的方法是采用现有的控制模板并根据您的需要对其进行修改。例如,复选框的控件模板可以在 CheckBox ControlTemplate Example 中找到。这应该显示如何在鼠标悬停时将背景更改为另一种颜色,但您也可以在某些内容下制作一条线更改颜色以模拟超链接。

【讨论】:

  • 啊,断开的链接一定是指断开的下划线。尝试 Julien Lebosquain 的建议后,我也看到了这一点。
  • 我意识到我可以通过重新定义模板来做到这一点,但是这种类型的解决方案似乎总是对我所追求的东西来说是重量级的。我只想控制控件的 MouseOver 状态,而不必将鼠标悬停在控件上,或者至少触发通常在 MouseOver 上发生的相同反应机制,而无需重新定义该控件的模板。如果 MouseOver 不是只读的,解决方案将非常简单,但是我可以理解为什么不是这样。
【解决方案3】:

UI 元素有一个 RaiseEvent 方法,可用于模拟鼠标事件。

XAML:

<Window x:Class="MouseOverTest.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Height="300" Width="300">
    <StackPanel>
        <TextBlock>  
            <Hyperlink MouseEnter="OnHyperlinkMouseEnter" Name="_hyperLink">  
                <TextBlock Text="My link text" /> 
            </Hyperlink> 
        </TextBlock>
        <Button Content="Simulate mouse enter" Click="OnButtonClick" />
    </StackPanel>
</Window>

后面的代码:

using System.Windows;
using System.Windows.Input;

namespace MouseOverTest
{
    public partial class Window1 : Window
    {
        public Window1()
        {
            InitializeComponent();
        }

        private void OnButtonClick(object sender, RoutedEventArgs e)
        {
            MouseEventArgs mouseEventArgs = new MouseEventArgs(Mouse.PrimaryDevice, 0);
            mouseEventArgs.RoutedEvent = Mouse.MouseEnterEvent;
            _hyperLink.RaiseEvent(mouseEventArgs);
        }

        private void OnHyperlinkMouseEnter(object sender, MouseEventArgs e)
        {
            MessageBox.Show("Mouse enter");
        }
    }
}

【讨论】:

  • 整洁!不是纯 XAML,但这是迄今为止最接近我真正追求的东西。
猜你喜欢
  • 2011-07-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-04-03
  • 1970-01-01
  • 2011-02-26
  • 2016-10-23
  • 1970-01-01
相关资源
最近更新 更多