英文:
Using RelayCommand CanExecute with CommunityToolkit.MVVM and Microsoft.Xaml.Behaviors.Wpf
问题
我正在尝试将 CommunityToolkit.MVVM (8.2.0) 与 Microsoft.Xaml.Behaviors.Wpf (1.1.39) 结合使用,并使用 RelayCommands CanExecute 功能来启用/禁用按钮。
在我的情况下,我需要查询 PreviewMouseDown 事件(而不是标准的点击事件),这可以通过 EventTrigger 很好地实现。不幸的是,使用 Behavior 时按钮的开/关状态在视觉上没有显示出来,但按钮的功能确实已正确启用/禁用。
我希望具有 EventTrigger 的按钮的行为与没有 EventTrigger 的按钮相同。我对 WPF 还很陌生,请原谅我
以下是 View.xaml(代码部分为空):
<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;
}
我尝试过向具有 EventTrigger 的按钮添加命令绑定,就像我在第一个按钮中所做的那样,但是某种方式看起来不对,或者我错了吗?后来,我想绑定更多的 EventTrigger,比如 PreviewMouseUp,所以似乎我不能避免将 Behaviors 与 MVVM 结合使用?
英文:
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?
答案1
得分: 2
很不幸,按钮的开/关状态在 Behavior 中没有进行视觉显示,但确实已正确启用/禁用按钮的功能。
这是预期的行为。如此博客文章所述," InvokeCommandAction
不会根据命令的 CanExecute
方法自动启用或禁用控件,不像具有 Command
属性并可以直接绑定到命令的控件。"
英文:
>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."
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论