简体   繁体   English

EventToCommandBehavior 在 MAUI 中为复选框抛出 InvalidOperationException

[英]EventToCommandBehavior throws InvalidOperationException in MAUI for checkbox

I need to run a command once a checkbox is checked/unchecked.选中/取消选中复选框后,我需要运行命令。 The checkboxes are rendered in the page via StackLayout's items source, EventToCommandBehavior is from MAUI CommunityToolkit.复选框通过 StackLayout 的项目源呈现在页面中,EventToCommandBehavior 来自 MAUI CommunityToolkit。

The exception is thrown when the page should be rendered, most likely when XAML is parsed and processed.当应该呈现页面时抛出异常,很可能是在解析和处理 XAML 时。 The Exception message says: "Operation is not valid due to the current state of the object.", which is not very helpful (I am missing what state, who is owner, what is invalid).异常消息说:“由于 object 的当前 state,操作无效。”,这不是很有帮助(我缺少什么 state,谁是所有者,什么是无效的)。

Maybe a callstact would help someone?也许 callstact 会帮助某人?

  at Microsoft.Maui.Controls.Binding.ApplyRelativeSourceBinding(BindableObject targetObject, BindableProperty targetProperty) in D:\a\_work\1\s\src\Controls\src\Core\Binding.cs:line 152
  at System.Threading.Tasks.Task.<>c.<ThrowAsync>b__128_0(Object state)
  at Android.App.SyncContext.<>c__DisplayClass2_0.<Post>b__0() in /Users/runner/work/1/s/xamarin-android/src/Mono.Android/Android.App/SyncContext.cs:line 36
  at Java.Lang.Thread.RunnableImplementor.Run() in /Users/runner/work/1/s/xamarin-android/src/Mono.Android/Java.Lang/Thread.cs:line 36
  at Java.Lang.IRunnableInvoker.n_Run(IntPtr jnienv, IntPtr native__this) in /Users/runner/work/1/s/xamarin-android/src/Mono.Android/obj/Release/net6.0/android-31/mcw/Java.Lang.IRunnable.cs:line 84
  at Android.Runtime.JNINativeWrapper.Wrap_JniMarshal_PP_V(_JniMarshal_PP_V callback, IntPtr jnienv, IntPtr klazz) in /Users/runner/work/1/s/xamarin-android/src/Mono.Android/Android.Runtime/JNINativeWrap

I've used the same technique several times in Xamarin. It works there as expected, but in MAUI following code throws InvalidOperationException.我在 Xamarin 中多次使用相同的技术。它按预期在那里工作,但在 MAUI 中,以下代码抛出 InvalidOperationException。 The content page and view model are created (the constructors pass) correctly, but somewhere later something throws an exception, and honestly don't know why.内容页面和视图 model 已正确创建(构造函数通过),但稍后某处抛出异常,老实说不知道为什么。

<StackLayout 
    BindableLayout.ItemsSource="{Binding GameVariants}">
    <BindableLayout.ItemTemplate>
        <DataTemplate x:DataType="bindable:SelectExpansion">
            <StackLayout Orientation="Horizontal" VerticalOptions="Center">
                <CheckBox
                    IsEnabled="{Binding IsExpansion}"
                    IsChecked="{Binding Selected}">
                    <CheckBox.Behaviors>
                        <toolkit:EventToCommandBehavior
                            EventName="CheckedChanged"
                            Command="{Binding Source={RelativeSource AncestorType={x:Type vm:SelectExpansionsPageViewModel}}, Path=SelectExpansionCommand}"
                            CommandParameter="{Binding .}" />
                    </CheckBox.Behaviors>
                </CheckBox>
                <Label Text="{Binding Expansion}" VerticalTextAlignment="Center" />
            </StackLayout>
        </DataTemplate>
    </BindableLayout.ItemTemplate>
</StackLayout>

The code behind contains only setting context via dependency.后面的代码仅包含通过依赖项设置上下文。

public partial class SelectExpansionsPage : ContentPage
{
    public SelectExpansionsPage(SelectExpansionsPageViewModel vm)
    {
        BindingContext = vm;
        InitializeComponent();
    }
}

And here is View model for page.这是页面的视图 model。

public partial class SelectExpansionsPageViewModel : ObservableObject
{
    public SelectExpansionsPageViewModel(Game state)
    {
        GameVariants = new ObservableCollection<SelectExpansion>(AvailableExpansions.Expansions.Select(item =>
        {
            item.Selected = state.Expansions.Contains(item.Expansion);

            return item;
        }));
    }

    public ObservableCollection<SelectExpansion> GameVariants { get; }
    
    [RelayCommand]
    public void SelectExpansion(SelectExpansion item)
    {
        Debug.WriteLine("Select item changed");
    }
}

After some research, I've found that behaviors aren't part of the visual tree (sorry, lost the link).经过一些研究,我发现行为不是可视化树的一部分(抱歉,链接丢失了)。

To overcome this one has to reference source binding via the reference, see the "This" which refers to the x:Name of the content page.要克服这一点,必须通过引用来引用源绑定,请参阅引用内容页面的x:Name“This” The ViewModel is just a strongly typed property of ContentPage which refers to the unboxed BindingContext . ViewModel只是ContentPage的强类型属性,它引用未装箱的BindingContext

Side note: The question refers to the .NET MAUI, however, I had to migrate back to the Xamarin Forms because at the time .NET MAUI has a lot of bugs that block development and app release.旁注:问题涉及 .NET MAUI,但是,我不得不迁移回 Xamarin Forms,因为当时 .NET MAUI 有很多阻碍开发和应用程序发布的错误。 The problem is the same for both frameworks.两个框架的问题是一样的。

<?xml version="1.0" encoding="utf-8"?>

<ContentPage
    xmlns="http://xamarin.com/schemas/2014/forms"
    xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
    xmlns:vm="clr-namespace:Everdell.ViewModels;assembly=Everdell"
    xmlns:toolkit="http://xamarin.com/schemas/2020/toolkit"
    x:Class="Everdell.Views.SelectExpansionsView"
    x:DataType="vm:SelectExpansionsViewModel"
    x:Name="This">
    <ContentPage.Content>
        <CheckBox>
            <CheckBox.Behaviors>
                <toolkit:EventToCommandBehavior
                    EventName="CheckedChanged"
                    Command="{Binding Source={x:Reference This}, Path=ViewModel.SelectExpansionCommand}"
                    CommandParameter="{Binding .}" />
            </CheckBox.Behaviors>
        </CheckBox>
    </ContentPage.Content>
</ContentPage>

Thanks for this, I needed to change Path=ViewModel.xxxx to Path=BindingContext.xxxx for it to work.为此,我需要将 Path=ViewModel.xxxx 更改为 Path=BindingContext.xxxx 才能正常工作。

Unfortunately the event triggers on all checks, including data load and scroll into view.不幸的是,该事件会触发所有检查,包括数据加载和滚动到视图中。 This is a problem with the event itself though.不过,这是事件本身的问题。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM