代码之家  ›  专栏  ›  技术社区  ›  jpierson

在wpf中模拟mouseover的任何方法

  •  0
  • jpierson  · 技术社区  · 15 年前

    我正在WPF中处理一个链接控件,它适合 text with icon links Windows UX指南中的案例。我想要的是在一个超链接中有一些文本出现在某个图像的右侧。

    在我的例子中,我首先使用一个文本块,它包含一个超链接,然后包含我的图像和一些文本。

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

    但问题是,图像比我的文本高会产生一种效果,即文本与底部对齐。不幸的是,我没有找到任何方法来控制文本块或超链接中的垂直对齐,所以我尝试了一种替代布局,其中超链接和代表我的矢量图标的矩形被分隔,以便使它们正确对齐,如下图所示。

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

    然而,问题在于,现在我的图标和超链接被分离了,当鼠标位于图标上时,我无法获得链接的鼠标悬停外观,反之亦然。另外,我的超链接有一个选项可以挂接一个命令,但是如果我使用超链接,矩形和StackPanel就不能挂接。命令图标不会执行该命令。

    所以这让我想到,我如何模拟给定控件的鼠标悬停,例如,当您实际鼠标悬停在框的关联文本上时,如何在框上获得鼠标悬停效果。我知道在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 回复  |  直到 8 年前
        1
  •  1
  •   Julien Lebosquain    15 年前

    第一个代码是前进的道路。你可以控制 Run 对准 BaselineAlignment . 设置为 Center 你的链接会按你想要的方式运行。

        2
  •  1
  •   Wallstreet Programmer    15 年前

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

    如果希望控件对mouseover事件的反应在默认情况下不是以其他方式可见,则需要重写其controlTemplate。通过使用现有的ControlTemplate并根据需要对其进行修改,这是最简单的方法。例如,可以在此处找到复选框的控件模板: http://msdn.microsoft.com/en-us/library/ms752319(v=VS.85).aspx 链接应该如何在mouseover上将背景更改为另一种颜色,但是您也可以在某些内容更改颜色下创建一行来模拟超链接。

        3
  •  1
  •   Wallstreet Programmer    15 年前

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