tags:

views:

51

answers:

2

I'm trying to make a mouse over for a stack panel in WPF using a custom DependencyProperty (StackPanels do not handle the MouseEnter event).

I've created a class for the DependencyProperty like so:

Public Class MouseEnterBehavior
  Public Shared Property MouseEnterProperty As DependencyProperty =
    DependencyProperty.RegisterAttached("MouseEnter",
                                        GetType(ICommand),
                                        GetType(MouseEnterBehavior),
                                        New PropertyMetadata(Nothing, AddressOf MouseEnterChanged))

  Public Shared Function GetMouseEnter(ByVal obj As DependencyObject) As ICommand
    Return CType(obj.GetValue(MouseEnterProperty), ICommand)
  End Function

  Public Shared Sub SetMouseEnter(ByVal obj As DependencyObject, ByVal value As ICommand)
    obj.SetValue(MouseEnterProperty, value)
  End Sub

  Public Shared Sub MouseEnterChanged(ByVal obj As DependencyObject, ByVal e As DependencyPropertyChangedEventArgs)
    Dim element As UIElement = TryCast(obj, UIElement)
    If element IsNot Nothing Then
      AddHandler element.MouseEnter, AddressOf uiElement_MouseEnter
    End If
  End Sub

  Public Shared Sub uiElement_MouseEnter(ByVal sender As Object, ByVal e As EventArgs)
    Dim uiElement As UIElement = TryCast(sender, UIElement)
    Dim command As ICommand = GetMouseEnter(uiElement)
    If command IsNot Nothing And command.CanExecute(uiElement) Then
      command.Execute(uiElement)
    End If
  End Sub
End Class

My View looks like this:

<Window x:Class="MainWindowView"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:vm="clr-namespace:WpfApplication1"
    Title="MainWindow" Height="350" Width="525">
    <Grid>
        <StackPanel Height="76" vm:MouseEnterBehavior.MouseEnterCommand="{Binding MouseEnteredCommand}" HorizontalAlignment="Left"  Margin="212,117,0,0" VerticalAlignment="Top" Width="88" Background="#72000000" />
    </Grid>
</Window>

And my ViewModel looks like this:

Public Class MainWindowViewModel
  Inherits ViewModelBase
  Implements INotifyPropertyChanged

  Private cmdMouseCommand As RelayCommand

  Public ReadOnly Property MouseEnteredCommand As ICommand
    Get
      If cmdMouseCommand Is Nothing Then
        cmdMouseCommand = New RelayCommand(AddressOf OnMouseEnterCommand)
      End If
      Return cmdMouseCommand
    End Get
  End Property

  Private Sub OnMouseEnterCommand(ByVal obj As Object)
    ''//Do something
  End Sub
End Class

Update

I was able to get the code to compile and run, however the binding doesn't occur. I can't seem to figure out why.

+1  A: 

I do believe that this is your problem:

DependencyProperty.RegisterAttached("MouseEnteredCommand",
                                    GetType(ICommand),
                                    GetType(MainWindowViewModel)

the first GetType should be the type of the property ( you are OK here )
the second GetType shuold be the type of the containing class, in your case "MouseEnterBehavior"

Muad'Dib
+1  A: 

You've registered the dependency property as MouseEnter*ed*Command, but try to bind to MouseEnterCommand.

On a side note, the binding won't set your DependencyProperty using the Set call you've provided; it will call SetValue directly. You'll need to pass a callback into the RegisterAttached so that you'll be notified.

Dan Bryant
@Dan Bryant, thanks a lot for your help. I think I'm starting to understand how this works a little better. I've made some changes to the code above showing my attempt to setup a callback for the DP. However, the command binding doesn't seem to occur. I put breakpoints on every method and none of them are hit. Any idea what I'm doing wrong?
hypoxide