伪造WPF鼠标悬停效果是否可行?

9

我有一个带有文本框和样式按钮的数据模板。当焦点在旁边的文本框上时,我希望按钮显示鼠标悬停状态。这可能吗?

我认为它需要类似以下的内容。我可以通过使用FindVisualChild和FindName获取文本框。然后我可以设置文本框上的GotFocus事件来执行某些操作。

_myTextBox.GotFocus += new RoutedEventHandler(TB_GotFocus);

在TB_GotFocus这里我卡住了。我可以获取想要显示鼠标悬停状态的按钮,但我不知道要发送什么事件。MouseEnterEvent是不允许的。

void TB_GotFocus(object sender, RoutedEventArgs e)
  {
     ContentPresenter myContentPresenter = FindVisualChild<ContentPresenter>(this.DataTemplateInstance);
     DataTemplate template = myContentPresenter.ContentTemplate;

     Button _button= template.FindName("TemplateButton", myContentPresenter) as Button;
     _button.RaiseEvent(new RoutedEventArgs(Button.MouseEnterEvent));

  } 

你能否发布你的控件模板让我们看看? - Bob King
2个回答

2
我认为无法伪造这个事件,但是你可以强制该按钮呈现出鼠标悬停的效果。
private void tb_GotFocus(object sender, RoutedEventArgs e)
{
    // ButtonChrome is the first child of button
    DependencyObject chrome = VisualTreeHelper.GetChild(button, 0);
    chrome.SetValue(Microsoft.Windows.Themes.ButtonChrome.RenderMouseOverProperty, true);
}

private void tb_LostFocus(object sender, RoutedEventArgs e)
{
    // ButtonChrome is the first child of button
    DependencyObject chrome = VisualTreeHelper.GetChild(button, 0);
    chrome.ClearValue(Microsoft.Windows.Themes.ButtonChrome.RenderMouseOverProperty);
}

你需要引用 PresentationFramework.Aero.dll 才能使其工作,但它只能在 Vista 平台的 Aero 主题下使用。

如果你想让它在其他主题下工作,你应该为每个你想支持的主题创建一个自定义控件模板。

参见 http://blogs.msdn.com/llobo/archive/2006/07/12/663653.aspx 获取提示。


我猜这对大多数人来说都可以,但是我正在使用自定义按钮模板,所以默认的Windows主题对我不起作用。 - Jippers

0
作为对jesperll评论的跟进,我认为您可以通过动态设置样式来避免为每个主题制作自定义模板/空模板。
这是我的窗口,定义了样式(但未设置任何内容)。
<Window x:Class="WpfApplication.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:WpfApplication"
Title="Window1" Height="300" Width="300">

<Window.Resources>
    <Style TargetType="{x:Type Button}" x:Key="MouseOverStyle">
        <Setter Property="Background">
            <Setter.Value>Green</Setter.Value>
        </Setter>
    </Style>
</Window.Resources>

<Grid Height="30">
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="3*"/>
        <ColumnDefinition Width="*"/>
    </Grid.ColumnDefinitions>
    <TextBox x:Name="MyTextBox" Grid.Column="0" Text="Some Text" Margin="2" GotFocus="TextBox_GotFocus" LostFocus="MyTextBox_LostFocus"/>
    <Button x:Name="MyButton" Grid.Column="1" Content="Button" Margin="2" MouseEnter="Button_MouseEnter" MouseLeave="Button_MouseLeave" />
</Grid>

你可以在.cs文件中使用事件来设置样式,而不是在模板中通过触发器来设置样式:

...

    public partial class Window1 : Window
{
    Style mouseOverStyle;
    public Window1()
    {
        InitializeComponent();
        mouseOverStyle = (Style)FindResource("MouseOverStyle");
    }
    private void TextBox_GotFocus(object sender, RoutedEventArgs e) { MyButton.Style = mouseOverStyle; }
    private void MyTextBox_LostFocus(object sender, RoutedEventArgs e) { MyButton.Style = null; }
    private void Button_MouseEnter(object sender, MouseEventArgs e) { ((Button)sender).Style = mouseOverStyle; }
    private void Button_MouseLeave(object sender, MouseEventArgs e) { ((Button)sender).Style = null; }
}

在构造函数中获取样式的引用,然后动态设置/取消它。这样,您可以在Xaml中定义您想要的样式外观,而不必依赖任何新的依赖项。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接