Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to create a single style for multiple mouse over events?

I have four buttons and four text boxes where each button is linked to one of the textblocks. When the mouse is over the button I want the corresponding textblock to fade in (and out on mouse leave). There are plenty of examples of this showing a single button and textblock where you can simply bind a datatrigger to the button name in the textblock style.

Here's what I've got so far (all of this is in a textblock style):

<DataTrigger Binding="{Binding ElementName=UpdateButton, Path=IsMouseOver}" Value="True">
    <DataTrigger.EnterActions>
         <BeginStoryboard>
              <Storyboard TargetProperty ="Opacity" Duration="00:00:01">
                   <DoubleAnimation From="0" To="1" Duration="00:00:01"/>
              </Storyboard>
         </BeginStoryboard>
    </DataTrigger.EnterActions>
    <DataTrigger.ExitActions>
         <BeginStoryboard>
              <Storyboard TargetProperty ="Opacity" Duration="00:00:01">
                   <DoubleAnimation From="1" To="0" Duration="00:00:01"/>
              </Storyboard>
         </BeginStoryboard>
    </DataTrigger.ExitActions>
</DataTrigger>

As of right now, when I mouse over the Update Button, all of the textblocks show instead of just the one associated with the Update Button.

To fix this I could create styles for each textblock by their name and bind to the appropriate button, but this is a huge amount of repetition. I could likely used "BasedOn" to separate the button binding, but then we're still duplicating all of the code for the Storyboards and whatnot. But does anyone know a better way?

It would seem like there should be a way create this all in a single style using a single generic binding but link the specific buttons to their textblocks, so the button only triggers the Storyboard for it's linked textblock. Anyone know how to do this, or a better way?

like image 740
liquidair Avatar asked Nov 07 '22 12:11

liquidair


1 Answers

A good way to handle this is to create a custom inherited TextBlock that can store reference to a button.

Example

using System.Windows;
using System.Windows.Controls;

//Custom TextBlock
public class SpecialTextBlock : TextBlock
{
    //This will be the button reference
    public Button BoundButton { get; set; }

    //Register the BoundButton as a dependency to allow binding
    public static readonly DependencyProperty ButtonProperty = DependencyProperty.Register
    (
        "BoundButton",
        typeof(Button),
        typeof(SpecialTextBlock),
        new FrameworkPropertyMetadata(default(Button))
    );
}

Now that your new SpecialTextBlock is set up, you can create a new style for it. Use your original style, but apply it to TargetType="local:SpecialTextBlock" instead of TargetType="TextBlock".

Then update your DataTrigger from your example within the style so that the trigger binds to itself (the SpecialTextBlock), and then looks at the referenced Button path.

<DataTrigger Binding="{Binding RelativeSource={RelativeSource Self}, Path=BoundButton.IsMouseOver}" Value="True">
...

Now you are set up and can create your TextBlocks like so without having to restyle.

//Set your BoundButton binding to specify which button triggers the animation.
<local:SpecialTextBlock BoundButton="{Binding ElementName=UpdateButton}" />
like image 197
Tronald Avatar answered Nov 15 '22 05:11

Tronald