Question

I understand my problem however I'm looking for advice on a solution:

        <Button.Style>
            <Style TargetType="{x:Type Button}" BasedOn="{StaticResource ButtonStyle}">
                <Style.Triggers>
                    <Trigger Property="IsMouseOver" Value="True">
                        <Setter Property="MouseOverControl" Value="True" />
                    </Trigger>
                </Style.Triggers>
            </Style>
        </Button.Style>

I'm trying to bind to a property inside my datacontext, basically I want to tell the DC when a control in my UI has the mouse over it. I think I'll only need this for two buttons and it doesn't matter which one it's over, therefore I don't need to bother with a complicated solution (I hope).

Problem is at the moment it's looking for Button.MouseOverControl which obviously doesn't exist, I'd like to understand how you might go about accessing the DC instead.

Thanks!

EDIT: So I've attempted to go down the attached property/behavior route, here is what I have so far:

public static class MouseBehaviour
{
    public static readonly DependencyProperty MouseOverProperty
        = DependencyProperty.RegisterAttached(
        "MouseOver",
        typeof(bool),
        typeof(MouseBehaviour),
        new FrameworkPropertyMetadata(false,
            FrameworkPropertyMetadataOptions.BindsTwoWayByDefault,
            MouseOverBindingPropertyChanged));

    public static bool GetMouseOver(DependencyObject obj)
    {
        return (bool)obj.GetValue(MouseOverProperty);
    }

    public static void SetMouseOver(DependencyObject obj, bool value)
    {
        obj.SetValue(MouseOverProperty, value);
    }

    private static void MouseOverBindingPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        var element = d as FrameworkElement;

        if (element != null)
        {
            // Unsure about this method..
        }

    }

}

Also I've added this to my button to try and link them, it appears to work:

ex:MouseBehaviour.MouseOver="{Binding MouseOverControl}"

However nothing happens, this is because I think it's working the wrong way around at the moment, so it is expecting my DC property to change but I want it so the MouseOverControl in my DC reflects the value of the IsMouseOver property of my button. Would it be as simple as:

SetMouseOver(element, element.IsMouseOver);

Or something similar?

Was it helpful?

Solution 2

So I ended up solving this by adding my own action to update a property because CallMethodAction is only available in Blend 4 which at the time I'm unable to use.

This question helped me considerably: Setting a property with an EventTrigger

In particular I'd like to direct you to user Neutrino's answer on that page (Here), the only part I needed to change was the XAML implementation:

        <i:Interaction.Triggers>
            <i:EventTrigger EventName="MouseEnter">
                <ex:SetPropertyAction PropertyName="MouseOverControl" TargetObject="{Binding}"
                                   PropertyValue="true" />
            </i:EventTrigger>
            <i:EventTrigger EventName="MouseLeave">
                <ex:SetPropertyAction PropertyName="MouseOverControl" TargetObject="{Binding}"
                                   PropertyValue="false"/>
            </i:EventTrigger>
        </i:Interaction.Triggers>

Quick explanation is whenever the mouse enters a button I've added these triggers to, it sets a property in my viewmodel/datacontext to mirror this, perfect! Credit to har07 for providing several alternate solutions which also would have worked in different situations (and if I could figure out attached behaviors!!)

OTHER TIPS

First thing come to mind is binding IsMouseOver property to MouseOverControl property in viewmodel directly without trigger. Unfortunately that scenario is not supported.

One possible workaround to address that limitation is using event that is raised whenever IsMouseOver property changed to trigger method/command in viewmodel. We can do that using interaction triggers. Since IsMouseOverChanged event doesn't exist, we can use 2 events (MouseEnter and MouseLeave) as alternative.

<Button>
    <i:Interaction.Triggers>
        <i:EventTrigger EventName="MouseEnter">
            <ei:CallMethodAction MethodName="MouseEnter" TargetObject="{Binding}"/>
        </i:EventTrigger>
    </i:Interaction.Triggers>
    <i:Interaction.Triggers>
        <i:EventTrigger EventName="MouseLeave">
            <ei:CallMethodAction MethodName="MouseLeave" TargetObject="{Binding}"/>
        </i:EventTrigger>
    </i:Interaction.Triggers>
</Button>

Then have corresponding methods in viewmodel :

public void MouseEnter()
{
    MouseOverControl = true;
}

public void MouseLeave()
{
    MouseOverControl = false;
}

Another possible way is by creating attached behavior for MouseOver so that you can bind it to viewmodel's property as demonstrated in this blog post.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top