Handling a Button's Click event in XAML?

c#, wpf, xaml

Solution

There definitely is a better way. With the help of the `Windows.Interactivity` assembly you are able to bind the event source to a singe class, containing only the associated action. With this you can almost do everything you ned.

The action class has to derive from TriggerAction. By overriding the `Invoke`-method you can specify the action.

Despite this scenario it also possible to bind the `EventTrigger` to a command (e.g. relay command), allowing a clean MMVM implementation.

xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"

<Button x:Name="button">
                        <i:Interaction.Triggers>
                            <i:EventTrigger SourceName="button" EventName="Click">
                                <app:MyAction/>
                            </i:EventTrigger>
                        </i:Interaction.Triggers>
                    </Button>
Public Class MyAction
    Inherits Interactivity.TriggerAction(Of UIElement)

    Protected Overrides Sub Invoke(parameter As Object)
        MsgBox("Clicked")
    End Sub

End Class

I updated the code to meet your specific requirements. The `TriggerAction` class now also contains a dependency property, which can be cound to your tab control:

<TabControl x:Name="tab"/>
                    <Button x:Name="button">
                        <i:Interaction.Triggers>
                            <i:EventTrigger SourceName="button" EventName="Click">
                                <app:MyAction Target="{Binding ElementName=tab}"/>
                            </i:EventTrigger>
                        </i:Interaction.Triggers>
                    </Button>
Public Class MyAction
    Inherits Interactivity.TriggerAction(Of UIElement)

    Protected Overrides Sub Invoke(parameter As Object)
        DirectCast(Target, TabControl).SelectedIndex = 0
    End Sub

    Shared Sub New()
        _targetProperty = DependencyProperty.Register(
          "Target",
          GetType(UIElement),
          GetType(MyAction),
          New UIPropertyMetadata(Nothing))
    End Sub

    Private Shared _targetProperty As DependencyProperty
    Public Shared ReadOnly Property TargetProperty As DependencyProperty
        Get
            Return _targetProperty
        End Get
    End Property

    Property Target As UIElement
        Get
            Return DirectCast(GetValue(TargetProperty), UIElement)
        End Get
        Set(value As UIElement)
            SetValue(TargetProperty, value)
        End Set
    End Property

End Class

Problem

This feels like a terribly basic question but I am sure there is a better way to do this. I have a `Button` in my UI which selects a specific tab and fire a `Command` from the `ViewModel` Here is the current code (which works fine): XAML: ``` <Button Content="Button!" Click="OnButtonClick" Command="{Binding WhateverCommand}" /> ``` Code behind: ``` private void OnButtonClick(object sender, RoutedEventArgs e) { theTab.IsSelected = true; } ``` Isn't there any cleaner, XAML-only way to do that UI operation? I was thinking about something like: ``` <Button Content="Button!" Click="OnButtonClick" Command="{Binding WhateverCommand}"> <Button.Triggers> <EventTrigger RoutedEvent="Click"> <Setter TargetName="theTab" Property="IsSelected" Value="True" /> </EventTrigger> </Button.Trigger> </Button> ``` But unfortunately it seems like the `EventTrigger` won't support a `Click` event. Why so? I am still sometimes confused with triggers after a few years working in WPF, and this pretty much sums it up. When trying to build that I have an error on the `Setter` line: ``` A value of type 'Setter' cannot be added to a collection or dictionary of type 'TriggerActionCollection'. ``` Thank you! EDIT since I was ask the XAML structure of my Window, it looks like this: ``` <DockPanel LastChildFill="True"> <Ribbon DockPanel.Dock="Top"> <Button Content="Button!" Click="OnButtonClick" Command="{Binding WhateverCommand}" /> </Ribbon> <TabControl> <TabItem x:Name="theTab" /> </TabControl> </DockPanel> ```

Original source

Related problems