-
-
Notifications
You must be signed in to change notification settings - Fork 49
Example for Shift+Click or Control+Click button? #73
Comments
I don't know any built-in way to do that. I suppose one can create custom action based on InvokeCommandAction for button with check for key gesture. |
Custom behavior for your use case (will be available in next release under
using Avalonia.Controls;
using Avalonia.Input;
using Avalonia.Interactivity;
using Avalonia.Xaml.Interactivity;
namespace Avalonia.Xaml.Interactions.Custom
{
/// <summary>
/// A behavior that listens for a <see cref="Button.ClickEvent"/> event on its source and executes its actions when that event is fired.
/// </summary>
public class ButtonClickEventTriggerBehavior : Trigger<Button>
{
private KeyModifiers _savedKeyModifiers = KeyModifiers.None;
/// <summary>
/// Identifies the <seealso cref="KeyModifiers"/> avalonia property.
/// </summary>
public static readonly StyledProperty<KeyModifiers> KeyModifiersProperty =
AvaloniaProperty.Register<ButtonClickEventTriggerBehavior, KeyModifiers>(nameof(KeyModifiers));
/// <summary>
/// Gets or sets the required key modifiers to execute <see cref="Button.ClickEvent"/> event handler. This is a avalonia property.
/// </summary>
public KeyModifiers KeyModifiers
{
get => GetValue(KeyModifiersProperty);
set => SetValue(KeyModifiersProperty, value);
}
/// <summary>
/// Called after the behavior is attached to the <see cref="Behavior.AssociatedObject"/>.
/// </summary>
protected override void OnAttached()
{
base.OnAttached();
if (AssociatedObject is { })
{
AssociatedObject.Click += AssociatedObject_OnClick;
AssociatedObject.AddHandler(InputElement.KeyDownEvent, Button_OnKeyDown, RoutingStrategies.Tunnel);
AssociatedObject.AddHandler(InputElement.KeyUpEvent, Button_OnKeyUp, RoutingStrategies.Tunnel);
}
}
/// <summary>
/// Called when the behavior is being detached from its <see cref="Behavior.AssociatedObject"/>.
/// </summary>
protected override void OnDetaching()
{
base.OnDetaching();
if (AssociatedObject is { })
{
AssociatedObject.Click -= AssociatedObject_OnClick;
AssociatedObject.RemoveHandler(InputElement.KeyDownEvent, Button_OnKeyDown);
AssociatedObject.RemoveHandler(InputElement.KeyUpEvent, Button_OnKeyUp);
}
}
private void AssociatedObject_OnClick(object sender, RoutedEventArgs e)
{
if (AssociatedObject is { } && KeyModifiers == _savedKeyModifiers)
{
Interaction.ExecuteActions(AssociatedObject, Actions, e);
}
}
private void Button_OnKeyDown(object sender, KeyEventArgs e)
{
_savedKeyModifiers = e.KeyModifiers;
}
private void Button_OnKeyUp(object sender, KeyEventArgs e)
{
_savedKeyModifiers = KeyModifiers.None;
}
}
} Example usage: <UserControl x:Class="BehaviorsTestApplication.Views.Pages.ButtonClickEventTriggerBehaviorView"
xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:i="using:Avalonia.Xaml.Interactivity"
xmlns:ia="using:Avalonia.Xaml.Interactions.Core"
xmlns:ic="using:Avalonia.Xaml.Interactions.Custom"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d" d:DesignWidth="600" d:DesignHeight="450">
<Grid RowDefinitions="*,Auto" ColumnDefinitions="30*,5,30*,5,30*">
<Canvas Grid.Row="0" Grid.Column="0" Grid.ColumnSpan="5" Margin="5" Background="{DynamicResource GrayBrush}">
<Ellipse Canvas.Left="{Binding Position, Mode=TwoWay}" Canvas.Top="200" Fill="{DynamicResource RedBrush}" Stroke="{DynamicResource YellowBrush}" StrokeThickness="5" Height="100" Width="100"/>
</Canvas>
<Button x:Name="MoveLeftButton" Content="Move Left (Hold Control)" Grid.Row="1" Grid.Column="0" Margin="5,0,0,5">
<i:Interaction.Behaviors>
<ic:ButtonClickEventTriggerBehavior KeyModifiers="Control">
<ia:InvokeCommandAction Command="{Binding MoveLeftCommand}"/>
</ic:ButtonClickEventTriggerBehavior>
</i:Interaction.Behaviors>
</Button>
<Button x:Name="ResetMoveButton" Content="Reset Move (Hold Control+Shift)" Grid.Row="1" Grid.Column="2" Margin="0,0,0,5">
<i:Interaction.Behaviors>
<ic:ButtonClickEventTriggerBehavior KeyModifiers="Control,Shift">
<ia:InvokeCommandAction Command="{Binding ResetMoveCommand}"/>
</ic:ButtonClickEventTriggerBehavior>
</i:Interaction.Behaviors>
</Button>
<Button x:Name="MoveRightButton" Content="Move Right (Hold Shift)" Grid.Row="1" Grid.Column="4" Margin="0,0,5,5">
<i:Interaction.Behaviors>
<ic:ButtonClickEventTriggerBehavior KeyModifiers="Shift">
<ia:InvokeCommandAction Command="{Binding MoveRightCommand}"/>
</ic:ButtonClickEventTriggerBehavior>
</i:Interaction.Behaviors>
</Button>
</Grid>
</UserControl> You can combine multiple triggers under one button behaviors collection: <Button Content="Left (Control), Reset (Hold Control+Shift), Right (Hold Shift)" Grid.Row="1" Grid.Column="0" Grid.ColumnSpan="5" Margin="5,0,0,5">
<i:Interaction.Behaviors>
<ic:ButtonClickEventTriggerBehavior KeyModifiers="Control">
<ia:InvokeCommandAction Command="{Binding MoveLeftCommand}"/>
</ic:ButtonClickEventTriggerBehavior>
<ic:ButtonClickEventTriggerBehavior KeyModifiers="Shift">
<ia:InvokeCommandAction Command="{Binding ResetMoveCommand}"/>
</ic:ButtonClickEventTriggerBehavior>
<ic:ButtonClickEventTriggerBehavior KeyModifiers="Control,Shift">
<ia:InvokeCommandAction Command="{Binding MoveRightCommand}"/>
</ic:ButtonClickEventTriggerBehavior>
</i:Interaction.Behaviors>
</Button> |
Excellent - those code samples helped me get up and running! Just to let you know, using the |
That sometime happens in previewer when assembly is not loaded so your solution is correct. |
Is there an example for shift+clicking or ctrl+clicking a button? I want my button to have one command, but if I shift+click the button I want it to invoke a different command
The text was updated successfully, but these errors were encountered: