在 Maui MvvM 项目中使用
EventToCommandBehaviors
(此处),我尝试在选择 Checkbox
时触发方法,但出现此异常:
System.Reflection.TargetInitationException:“调用目标已引发异常”。
我在“真实”项目和沙盒解决方案上得到了完全相同的行为来重新创建问题。我还在项目的其他地方使用
EventToCommandBehaviors
,所以我知道我可以让它工作。
当代码尝试运行 XAML 时抛出异常。
问题可能出在我的 Binding 上,但我没有发现它有什么问题,除了它位于
CollectionView
深处。
我还在绑定到
DataTrigger
的 Frame
控件上使用 Checkbox
,但将其注释掉不会影响异常。
这是 XAML(很抱歉它太宽了):
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:viewmodel="clr-namespace:Sandbox.ViewModel"
xmlns:model="clr-namespace:Sandbox.Model"
xmlns:toolkit="http://schemas.microsoft.com/dotnet/2022/maui/toolkit"
x:DataType="viewmodel:CheckboxMethodPageViewModel"
x:Class="Sandbox.View.CheckboxMethodPage"
Title="CheckboxMethodPage">
<Grid RowDefinitions="Auto,*">
<Label Grid.Row="0"
Margin="20,0,20,0" />
<CollectionView Grid.Row="1" ItemsSource="{Binding Things}">
<CollectionView.ItemTemplate>
<DataTemplate >
<Grid Padding="5">
<Frame Style="{StaticResource CardView}">
<HorizontalStackLayout>
<Label Text="{Binding Name}"/>
<CheckBox>
<CheckBox.Behaviors>
<toolkit:EventToCommandBehavior EventName="CheckedChangedCommand"
Command="{Binding Source={RelativeSource AncestorType={x:Type viewmodel:CheckboxMethodPageViewModel}}, Path=CheckChanged}"/>
</CheckBox.Behaviors>
</CheckBox>
</HorizontalStackLayout>
<Frame.Triggers>
<DataTrigger TargetType="Frame"
Binding="{Binding Source={x:Reference checkBox}, Path=IsChecked}"
Value="true">
<Setter Property="Background"
Value="#dee7ef" />
<Setter Property="BorderColor"
Value="#952e31" />
</DataTrigger>
</Frame.Triggers>
</Frame>
</Grid>
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
</Grid>
</ContentPage>
下面是对应ViewModel中的相关代码:
[RelayCommand]
private void CheckChanged()
{
return;
}
我还针对
Checkbox
XAML 代码和 C# 方法尝试了我能想到的所有变体,但我总是遇到相同的异常。
这是一个例子:
<CheckBox x:Name="checkBox">
<CheckBox.Behaviors>
<toolkit:EventToCommandBehavior EventName="CheckedChanged"
Command="{Binding Source={RelativeSource AncestorType={x:Type viewmodel:CheckboxMethodPageViewModel}}, Path=CheckChangedCommand}"
CommandParameter="{Binding .}"/>
</CheckBox.Behaviors>
</CheckBox>
[RelayCommand]
private async Task CheckChanged(ThingamaBob thingamajig)
{
return;
}
我在这个项目的其他地方使用了
EventToCommandBehavior
,所以我知道我可以让它工作。
我非常乐意接受解决方法的建议。我最初尝试使用
CommunityToolkit.MVVM
(参见 here),但我也无法让它发挥作用。
====================================================== ========
我认为,如果您尝试为其创建方法的控件已经有一个事件,则必须使用它。另外,当涉及到
EventToCommandBehavior
和 CheckBox
时,也很奇怪。
无论如何,我得到了解决方案这里。
我不知道它到底是如何工作的,但这是我的
EventToCommandBehavior
命令,当 CheckBox
位于 CollectionView
内部时:
为您的内容页面命名:
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:toolkit="http://schemas.microsoft.com/dotnet/2022/maui/toolkit"
...
x:Name="this">
这是
CheckBox
控件。请注意,我使用的事件是 CheckedChange
,但您可以随意命名您的实际方法。 AddToCase
是一个布尔值,它是我在 CollectionView
中使用的模型对象的属性:
<CheckBox.Behaviors>
<toolkit:EventToCommandBehavior Command="{Binding Source={x:Reference this},
Path=BindingContext.AddToListCommand}"
CommandParameter="{Binding AddToCase}"
EventName="CheckedChanged" />
</CheckBox.Behaviors>
这是我的方法:
[RelayCommand]
public static void AddToList(bool value)
{
if (value)
{
// do the thing
}
else
{
// do theother thing
}
}
我遇到的问题是我位于集合视图中,需要传递参数以及布尔值。所以,是的。
出现此异常是因为 xaml 中的命令参数不是 bool。当您使用 eventtocommand 行为时,您还需要传递正确的参数。
CheckedChanged事件的参数是后面代码中的CheckedChangedEventArgs。当你想在viewmodel中绑定命令时,你可以自定义EventArgsContervor:
public class CheckedChangedArgsConvertor : BaseConverterOneWay<CheckedChangedEventArgs?, bool>
{
public override bool DefaultConvertReturnValue { get; set; } = false;
public override bool ConvertFrom(CheckedChangedEventArgs value, CultureInfo culture)
{
return value.Value;
}
}
然后在xaml中使用它:
<ContentPage.Resources>
<local:CheckedChangedArgsConvertor x:Key="ArgsToInt"/>
</ContentPage.Resources>
<StackLayout x:Name="layout">
<CheckBox >
<CheckBox.Behaviors>
<mct:EventToCommandBehavior EventName="CheckedChanged"
Command="{Binding AddToListCommand}"
EventArgsConverter="{StaticResource ArgsToInt}"/>
</CheckBox.Behaviors>
</CheckBox>
我已经对此进行了测试,并且命令绑定有效。更多信息,您可以参考Binding value converters的官方文档和ItemTappedEventArgsConverter的源代码。