Есть ли способ имитировать MouseOver в WPF?

Я работаю над элементом управления ссылками в WPF, который соответствует текст со ссылками на значки в Руководстве по пользовательскому интерфейсу Windows. Я хочу иметь некоторый текст в гиперссылке, которая появляется справа от некоторого изображения.

В моем случае я начал с использования TextBlock, который содержал Hyperlink, который затем содержал мое изображение и некоторый текст.

<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 и прямоугольник, представляющие мою векторную иконку, разделены, чтобы заставить их правильно выровняйте, как показано ниже.

<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 имеет для , который можно использовать для указания того, какой элемент управления он помечает, что в основном будет делать то, что я ищу. Также я могу представить, что в других сценариях было бы неплохо иметь метку, которая при наведении указателя мыши показывает соответствующее текстовое поле, как если бы мышь находилась над ним, и, возможно, при щелчке фокус также передается соответствующему текстовому полю. На данный момент, хотя меня в основном интересует, как заставить метку или элемент, подобный метке, в 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>

person jpierson    schedule 25.05.2010    source источник
comment
Содержимое второго XML-блока сформировано неправильно — <Hyperlink>My link text<Hyperlink> заканчивается на <Hyperlink>, а не на </Hyperlink>.   -  person Peter Mortensen    schedule 09.08.2019


Ответы (3)


Первый код - это путь. Вы можете управлять выравниванием Run с помощью BaselineAlignment. Установите его на Center, и ваша ссылка будет вести себя так, как вы хотели.

person Julien Lebosquain    schedule 25.05.2010
comment
Это действительно решает мою первоначальную проблему, связанную с выравниванием, но я заметил, что после его реализации мой значок также становится подчеркнутым, и, что еще хуже, подчеркивание разрывается между текстом и изображением. Я думаю, мне придется найти другую стратегию, в которой все еще остается фундаментальный вопрос, как имитировать MouseOver в WPF. - person jpierson; 26.05.2010

Элементы пользовательского интерфейса имеют метод 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");
        }
    }
}
person Wallstreet Programmer    schedule 26.05.2010
comment
Аккуратный! Не чистый XAML, но пока это самое близкое к тому, что мне действительно нужно. - person jpierson; 26.05.2010

Использование 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. Это должно показать, как изменить фон на другой цвет при наведении курсора мыши, но вы также можете сделать линию под каким-либо содержимым, меняющим цвет, чтобы имитировать гиперссылку.

person Wallstreet Programmer    schedule 25.05.2010
comment
Ах, под неработающей ссылкой вы должны иметь в виду неработающее подчеркивание. Я тоже это увидел, когда опробовал предложение Жюльена Лебоскейна. - person jpierson; 26.05.2010
comment
Я понимаю, что могу сделать это, переопределив шаблон, однако такой тип решения всегда кажется тяжеловесным для того, что мне нужно. Я просто хочу управлять состоянием MouseOver элемента управления без необходимости наводить указатель мыши на элемент управления или, по крайней мере, запускать те же реактивные механизмы, которые обычно выполняются при MouseOver, без необходимости переопределять шаблон этого элемента управления. Если бы MouseOver не был только для чтения, решение было бы очень простым, однако я могу понять, почему это не так. - person jpierson; 26.05.2010