0

I have a window with a UserControl, that UserControl has an element. If I move the mouse over the element inside the UserControl, I want that some other elements inside the Window to react (for example: hide them).

enter image description here

<Window x:Class="WpfApplication4.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="MainWindow" Height="350" Width="525"
    xmlns:local="clr-namespace:WpfApplication4"
    >
<DockPanel>
    <Grid Width="50" Height="50" Background="Yellow">
        <Grid.Style>
            <Style TargetType="Grid">
                <Style.Triggers>

                    <!-- When hovering innerControl inside userControl  this grid should become invisible, of course this doesn't work, it hides the element if I move the mouse over any part of the usercontrol-->

                    <DataTrigger Binding="{Binding userControl.IsMouseOver, ElementName=userControl}" Value="True">
                        <Setter Property="Visibility" Value="Collapsed" />
                    </DataTrigger>
                </Style.Triggers>
            </Style>
        </Grid.Style>
    </Grid>
    <local:userControl x:Name="userControl" Width="300" Height="300"/>
</DockPanel>

UserControl

<UserControl x:Class="WpfApplication4.userControl"
         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
         xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
         xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
         mc:Ignorable="d" 
         d:DesignHeight="300" d:DesignWidth="300"
         Background="Red"
         >
    <Grid>
    <Grid x:Name="innerControl" Background="Blue" Width="100" Height="100"/>
</Grid>

public partial class userControl : UserControl
{
    public userControl()
    {
        InitializeComponent();
    }

    //This is far from working

    public new bool  IsMouseOver
    {
        get { return (bool)GetValue(IsMouseOverProperty); }
        set { SetValue(IsMouseOverProperty, value); }
    }

    public new static readonly DependencyProperty IsMouseOverProperty =
        Border.IsMouseOverProperty.AddOwner(typeof(Border));
}

I know I have to use Dependency Properties, but I can't adapt the examples I have found to this problem.

The One
  • 4,560
  • 5
  • 36
  • 52
  • Why are you making the "IsMouseOver" property yourself? I'm pretty sure that all FrameworkElements has that property inherently. – Falgantil May 13 '15 at 21:10
  • Yeah, that code is wrong. ( //This is far from working) – The One May 13 '15 at 21:11
  • In regards to your original question, off the top of my head I would say that's probably not possible, unless you create all the standard "IsMouseOver" code AGAIN, and have it react to the inner control instead of the UserControl as a whole. Which seems like a lot of work, so I'd recommend instead just doing the work in the original xaml view. – Falgantil May 13 '15 at 21:13

1 Answers1

1

Just in case anyone cares, here's the solution

Adapted from this answer: https://stackoverflow.com/a/317699/3596441

Expose child controls properties in UserControl:

public partial class userControl : UserControl
{
    public userControl()
    {
        InitializeComponent();
        DependencyPropertyDescriptor descriptor = DependencyPropertyDescriptor.FromProperty(FrameworkElement.IsMouseOverProperty, typeof(FrameworkElement));
        descriptor.AddValueChanged(this.innerControl, new EventHandler(OnIsMouseOverChanged));

    }

    // Dependency Property Declaration
    private static DependencyPropertyKey ElementIsMouseOverPropertyKey = DependencyProperty.RegisterReadOnly("ElementIsMouseOver", typeof(bool),typeof(userControl), new PropertyMetadata());
    public static DependencyProperty ElementIsMouseOverProperty = ElementIsMouseOverPropertyKey.DependencyProperty;


    public bool ElementIsMouseOver
    {
        get { return (bool)GetValue(ElementIsMouseOverProperty); }
    }
    private void SetIsMouseOver(bool value)
    {
        SetValue(ElementIsMouseOverPropertyKey, value);
    }

    // Dependency Property Callback
    // Called when this.MyElement.ActualWidth is changed
    private void OnIsMouseOverChanged(object sender, EventArgs e)
    {
        this.SetIsMouseOver(this.innerControl.IsMouseOver);
    }


}

Use like this:

<Window x:Class="WpfApplication4.MainWindow"
  ...
    xmlns:local="clr-namespace:WpfApplication4"
    >
<DockPanel>
    <Grid DockPanel.Dock="Left" Width="100" Height="100" Background="Yellow">
        <Grid.Style>
            <Style TargetType="Grid">
                <Style.Triggers>
                    <DataTrigger Binding="{Binding ElementIsMouseOver, ElementName=userControl}" Value="True">
                        <Setter Property="Visibility" Value="Collapsed"/>
                    </DataTrigger>
                </Style.Triggers>
            </Style>
        </Grid.Style>
    </Grid>

    <local:userControl x:Name="userControl" Width="300" Height="300"/>

</DockPanel>

Community
  • 1
  • 1
The One
  • 4,560
  • 5
  • 36
  • 52