I am trying to combine the CommunityToolkit.MVVM (8.2.0) with Microsoft.Xaml.Behaviors.Wpf (1.1.39) and enable/disable a button using RelayCommands CanExecute functionality.
In my case I need to query the PreviewMouseDown event (Not a standard click event), this works quite well with an EventTrigger. Unfortunately, the on/off state is not visually displayed for the button with Behavior - but the functionality of the button is indeed properly enabled/disabled.
I want the button with EventTrigger to behave the same as the one without. I am quite new to WPF, please forgive me :)
Here is the View.xaml (code behind is "empty"):
<Window x:Class="Example.View"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:i="http://schemas.microsoft.com/xaml/behaviors"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:Example"
mc:Ignorable="d"
Title="View" SizeToContent="WidthAndHeight" ResizeMode="NoResize">
<Window.DataContext>
<local:ViewModel/>
</Window.DataContext>
<StackPanel Margin="5" Orientation="Horizontal">
<Button Command="{Binding ToggleAllowenceCommand}" Content="Toggle Allowence"/>
<StackPanel Margin="5,0,0,0">
<Button Command="{Binding MouseDownCommand}">
<TextBlock Text="Button without xaml.behaviors"/>
</Button>
<Button Margin="0,5,0,0">
<i:Interaction.Triggers>
<i:EventTrigger EventName="PreviewMouseDown">
<i:InvokeCommandAction Command="{Binding MouseDownCommand}"/>
</i:EventTrigger>
</i:Interaction.Triggers>
<TextBlock Text="Button with xaml.behaviors"/>
</Button>
</StackPanel>
</StackPanel>
</Window>
ViewModel.cs:
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
namespace Example;
partial class ViewModel : ObservableObject
{
public ViewModel() { }
[ObservableProperty]
[NotifyCanExecuteChangedFor(nameof(MouseDownCommand))]
private bool _allowence = false;
private bool CanExecuteMouseDown() => Allowence;
[RelayCommand(CanExecute = nameof(CanExecuteMouseDown))]
private void MouseDown() { }
[RelayCommand]
private void ToggleAllowence() => Allowence = !Allowence;
}
I experimented with adding a command binding to the button with the EventTrigger like I did with the first button - but somehow it looks wrong, or am I wrong? Later I wanted to bind more EventTriggers - like PreviewMouseUp, so it seems I can't avoid Behaviors in combination with MVVM?
This is the expected behaviour. As stated in this blog post, "an
InvokeCommandActiondoesn't automatically enable or disable the control based on the command'sCanExecutemethod, unlike controls that have aCommandproperty and can be bound directly to a command."