views:

1674

answers:

2

I have a data template with a textbox and a button with some styles on it. I would like to have the button show the mouse over state when focus is on the textbox beside it. Is this possible?

I figure it would involve something like this. I can get the textbox through use of FindVisualChild and FindName. Then I can set the GotFocus event on the textbox to do something.

_myTextBox.GotFocus += new RoutedEventHandler(TB_GotFocus);

Here in TB_GotFocus I'm stuck. I can get the button I want to show the mouse over state of, but I don't know what event to send to it. MouseEnterEvent isn't allowed.

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

  }
+1  A: 

I don't think it's possible to fake the event but you can force the button to render itself as if it had MouseOver.

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

you need to reference PresentationFramework.Aero.dlll for this to work and then it will only work on Vista for the Aero theme.

If you want it to work for other themes you should make a custom controltemplate for each of the theme you want to support.

See http://blogs.msdn.com/llobo/archive/2006/07/12/663653.aspx for tips

jesperll
This would work for most people I suspect, but I'm using a custom button template so the default windows theme won't work for me.
Jippers
A: 

As a follow up to jesperll's comment, I think you can get around making a custom template for each theme by dynamically setting the style to the one you want / null.

Here is my window, with the style defined (but not set to anything).

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

Instead of setting the style via triggers in the template, you can use events in your .cs file like so:

...

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

You get a reference to the style in the constructor and then dynamically set it / unset it. This way, you can define what you want your style to look like in Xaml, and you don't have to rely on any new dependencies.

Mick