有没有办法在WPF中模拟MouseOver?

时间:2010-05-25 19:03:53

标签: wpf mouseover hyperlink

我正在使用WPF中的链接控件,该控件符合Windows UX指南中的text with icon links大小写。我想在某个图像右侧出现的超链接中有一些文本。

在我的情况下,我开始使用包含超链接的TextBlock,然后包含我的图像和一些文本。

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

然而,问题在于图像比我的文字高,产生了文本与底部对齐的效果。不幸的是我还没有找到一种方法来控制TextBlock或Hyperlink中的垂直对齐,所以我尝试了另一种布局,其中代表我的矢量图标的Hyperlink和Rectangle是分开的,以便让它们到达如下所示正确对齐。

<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>

然而问题是,现在我的Icon和我的超链接已经分开,当鼠标悬停在我的图标上时,我没有得到我的链接的MouseOver外观,反之亦然。另外我的Hyperlink有一个选项可以连接一个Command,但Rectangle和StackPanel没有,所以如果我使用Hyperlink.Command,图标将不会执行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>

3 个答案:

答案 0 :(得分:1)

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

答案 1 :(得分:1)

使用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>

如果您希望控件对鼠标悬停事件的显示作出反应,则默认情况下需要覆盖其controltemplate。这是最简单的方法,通过采用现有的控制模板并根据您的需要进行修改。例如,可以在此处找到复选框的控件模板:http://msdn.microsoft.com/en-us/library/ms752319(v=VS.85).aspx 该链接应该如何在鼠标悬停时将背景更改为另一种颜色,但您也可以在某些内容更改颜色下创建一条线以模拟超链接。

答案 2 :(得分:1)

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");
        }
    }
}