22

I have a style, and I want to bind a command to the EventSetter's Handler with RelativeSource. The command is in the viewModel.

<Style x:Key="ItemTextBlockEventSetterStyle" TargetType="{x:Type TextBlock}">
    <EventSetter Event="MouseLeftButtonDown" 
                 Handler="{Binding TextBlockMouseLeftButtonDownCommand, 
                           RelativeSource={RelativeSource Self}}"/>
</Style>

The problem is that I get an error, because something is wrong with this (maybe it's not possible to do this in such easy way)

I've googled a lot before, and I found the AttachedCommandBehaviour, but I think it doesn't work with style.

Could you give some hints on how to solve this problem?

Update 13/10/2011

I found this in the MVVM Light Toolkit EventToCommand example program:

        <Button Background="{Binding Brushes.Brush1}"
            Margin="10"
            Style="{StaticResource ButtonStyle}"
            Content="Simple Command"
            Grid.Row="1"
            ToolTipService.ToolTip="Click to activate command">
        <i:Interaction.Triggers>
            <i:EventTrigger EventName="Click">
                <cmd:EventToCommand Command="{Binding SimpleCommand}" />
            </i:EventTrigger>
            <i:EventTrigger EventName="MouseLeave">
                <cmd:EventToCommand Command="{Binding ResetCommand}" />
            </i:EventTrigger>
        </i:Interaction.Triggers>
    </Button>

But here, the binding isn't in the style. How can I put this EventToCommand to the style of the button?

Athafoud
  • 2,898
  • 3
  • 40
  • 58
Zoltán Barna
  • 463
  • 2
  • 4
  • 12

3 Answers3

29

Right now you are binding the MouseLeftButtonDown Event to TextBlock.TextBlockMouseLeftButtonDownCommand. TextBlockMouseLeftButtonDownCommand is not a valid property for a TextBlock, nor does it sound like it's an Event Handler.

I use the AttachedCommandBehavior all the time in styles for hooking up a Command to an Event. The syntax usually looks like this (note the DataContextin the Command Binding):

<Style x:Key="ItemTextBlockEventSetterStyle" TargetType="{x:Type TextBlock}">
    <Setter Property="local:CommandBehavior.Event" Value="MouseLeftButtonDown" />
    <Setter Property="local:CommandBehavior.Command"
            Value="{Binding DataContext.TextBlockMouseLeftButtonDownCommand, 
                            RelativeSource={RelativeSource Self}}" />
</Style>

The alternative is to hook the EventSetter up to an event in the code-behind, and process the command from there:

<Style x:Key="ItemTextBlockEventSetterStyle" TargetType="{x:Type TextBlock}">
    <EventSetter Event="MouseLeftButtonDown" 
                 Handler="TextBlockMouseLeftButtonDown"/>
</Style>

Event handler in code behind...

void TextBlockMouseLeftButtonDown(object sender, MouseEventArgs e)
{
    var tb = sender as TextBlock;
    if (tb != null)
    {
        MyViewModel vm = tb.DataContext as MyViewModel;

        if (vm != null && TextBlockMouseLeftButtonDownCommand != null
            && TextBlockMouseLeftButtonDownCommand.CanExecute(null))
        {
            vm.TextBlockMouseLeftButtonDownCommand.Execute(null)
        }
    }
}
Rachel
  • 130,264
  • 66
  • 304
  • 490
  • Nice idea to put the command execution to the event, but I will try the AttachCommandBehavior tomorrow! Thanks a lot for the answer! – Zoltán Barna Oct 13 '11 at 16:24
  • AttachCommandBehavior works perfectly. One thing that I'm not sure how to solve. I want to bind commands not only for one event, and I found this kind of solution: http://stackoverflow.com/questions/926451/how-can-i-attach-two-attached-behaviors-to-one-xaml-element It's really good, but how can I put this CommandBehaviorCollection to the style? Thanks in advance for your answer! – Zoltán Barna Oct 14 '11 at 06:14
  • @ZoltánBarna It does not appear to work in Styles or Templates – Rachel Oct 14 '11 at 11:59
  • Hello Rachel, thank you very much. I had the exact same problem as the OP, and where from System.Windows.Interactivity fails, AttachedCommandBehavior works perfectly. – Golvellius Feb 14 '13 at 10:03
5

As you are using MVVM, I suggest you Galasoft MVVM Light Toolkit EventToCommand

Philippe Lavoie
  • 2,583
  • 5
  • 25
  • 39
0

My answer on this question does the trick without any external tool kits/libraries. However, it does not use RelativeSource, and it is not 100% MVVM. It requires one line of code in a code-behind event handler.

Micah Vertal
  • 564
  • 1
  • 7
  • 16