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> ```