1

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?

Tom Oeser
  • 632
  • 1
  • 5
  • 8

1 Answers1

2

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.

This is the expected behaviour. As stated in this blog post, "an InvokeCommandAction doesn't automatically enable or disable the control based on the command's CanExecute method, unlike controls that have a Command property and can be bound directly to a command."

mm8
  • 163,881
  • 10
  • 57
  • 88