.net MAUI DataTemplate,其 CollectionView 在其 ItemTemplate 中包含 <ContentPresenter />,“未检测到已安装的组件”

问题描述 投票:0回答:1

我们有许多显示模型列表的视图,在每个视图中,点击一个项目会显示一个操作表。

一切运行良好,但我们希望利用 ControlTemplate 来确保视图之间的一致性。第一次尝试似乎有效,但事实证明它只有效,因为 ItemsSource 中只有一个项目。一旦 ItemsSource 包含多个项目,就会引发“未检测到已安装的组件”异常。第一个项目仍然正确渲染,并且点击它可以按预期运行。

以下是正在播放的文件:

ListViewsTemplate.xaml

<ContentView xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
         xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
         x:Class="MauiIssues.Controls.ListViewsTemplate"
         ControlTemplate="{DynamicResource ContainerTemplate}"
         x:Name="this">
<ContentView.Resources>
    <ResourceDictionary>
        <ControlTemplate x:Key="ContainerTemplate">
            <Frame BindingContext="{x:Reference this}" Padding="10, 0, 10, 0">
                <CollectionView ItemsSource="{TemplateBinding ItemsSource}">
                    <CollectionView.ItemsLayout><LinearItemsLayout Orientation="Vertical" /></CollectionView.ItemsLayout>
                    <CollectionView.ItemTemplate>
                        <DataTemplate>
                            <Grid>
                                <Frame>
                                    <Frame.GestureRecognizers>
                                        <TapGestureRecognizer 
                                            Command="{TemplateBinding ItemTapped}"
                                            CommandParameter="{Binding .}" />
                                    </Frame.GestureRecognizers>
                                    <ContentPresenter />
                                </Frame>
                                <Rectangle IsVisible="{OnPlatform false, Android=True}" HeightRequest="2" Fill="Black"/>
                            </Grid>
                        </DataTemplate>
                    </CollectionView.ItemTemplate>
                </CollectionView>
            </Frame>
        </ControlTemplate>
    </ResourceDictionary>
</ContentView.Resources>

ListViewsTemplate.xaml.cs

using System.Collections;
using System.Windows.Input;

namespace MauiIssues.Controls
{
    public partial class ListViewsTemplate : ContentView
    {
        public IEnumerable ItemsSource
        {
            get => (IEnumerable)GetValue(ItemsSourceProperty);
            set => SetValue(ItemsSourceProperty, value);
        }
        public static readonly BindableProperty ItemsSourceProperty =
            BindableProperty.Create(nameof(ItemsSource), typeof(IEnumerable), typeof(ListViewsTemplate), defaultBindingMode: BindingMode.TwoWay);
        
        public ICommand ItemTapped
        {
            get => (ICommand)GetValue(ItemTappedProperty);
            set => SetValue(ItemTappedProperty, value);
        }
        public static readonly BindableProperty ItemTappedProperty =
            BindableProperty.Create(nameof(ItemTapped), typeof(ICommand), typeof(ListViewsTemplate), defaultBindingMode: BindingMode.TwoWay);

        public ListViewsTemplate() { InitializeComponent(); }

    }
}

ListViewsTemplate.xaml

<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:model="clr-namespace:MauiIssues.Models"
             xmlns:uc="clr-namespace:MauiIssues.Controls"
             xmlns:viewmodel="clr-namespace:MauiIssues.ViewModels"
             x:Class="MauiIssues.Views.ListViewsTemplate"
             x:DataType="viewmodel:ListViewsTemplateViewModel">
    <uc:ListViewsTemplate ItemsSource="{Binding Items}" ItemTapped="{Binding ItemTappedCommand}" VerticalOptions="StartAndExpand" >
        <Label BindingContext="{Binding Source={RelativeSource AncestorType={x:Type model:ListViewsTemplateModel}}}" 
               x:DataType="{x:Type model:ListViewsTemplateModel}" 
               Text="{Binding Name}" />
    </uc:ListViewsTemplate>
</ContentPage>

ListViewsTemplate.xaml.cs

using MauiIssues.ViewModels;

namespace MauiIssues.Views
{
    public partial class ListViewsTemplate : ContentPage
    {
        public ListViewsTemplateViewModel ViewModel { get; }

        public ListViewsTemplate()
        {
            base.BindingContext = this.ViewModel = new ListViewsTemplateViewModel();
            InitializeComponent();
        }

        protected override async void OnAppearing()
        {
            await this.ViewModel.OnAppearing();
            base.OnAppearing();
        }
    }
}

ListViewsTemplateViewModel.cs

using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using MauiIssues.Models;
using System.Collections.ObjectModel;

namespace MauiIssues.ViewModels
{
    public partial class ListViewsTemplateViewModel : ObservableObject
    {
        public ObservableCollection<ListViewsTemplateModel> Items { get; } = new ();

        [RelayCommand]
        async Task ItemTapped(ListViewsTemplateModel item)
        {
            await App.Current.MainPage.DisplayAlert("tapped item", item.Name, "OK");
        }

        public async Task OnAppearing() 
        {
            this.Items.Add(new ListViewsTemplateModel() { Name = $"Item {this.Items.Count + 1}" });
            await Task.CompletedTask;
        }
    }
}

当您第一次导航到该视图时,一切都很顺利。当您离开并返回到您看到的视图时:

未检测到已安装的组件。

在 System.Runtime.InteropServices.Marshal.ThrowExceptionForHR(Int32 错误代码) 在 WinRT.DelegateExtensions.DynamicInvokeAbi(委托 del,Object[] invoke_params) 在 ABI.System.Collections.Generic.IVectorMethods

1.Append(IObjectReference obj, T value) at ABI.System.Collections.Generic.IListMethods
1.Add(IObjectReference obj, T item) 在 Microsoft.UI.Xaml.Controls.UIElementCollection.Add(UIElement 项) 在 Microsoft.Maui.Handlers.ContentViewHandler.UpdateContent(IContentViewHandler 处理程序) 在 Microsoft.Maui.Handlers.ContentViewHandler.MapContent(IContentViewHandler 处理程序,IContentView 页面) 在 Microsoft.Maui.Controls.Element.OnPropertyChanged(String propertyName) 在 Microsoft.Maui.Controls.BindableObject.SetValueActual(BindableProperty 属性、BindablePropertyContext 上下文、对象值、布尔值 currentApplying、SetValueFlags 属性、布尔值静默) 在 Microsoft.Maui.Controls.BindableObject.SetValueCore(BindableProperty 属性、对象值、SetValueFlags 属性、SetValuePrivateFlags privateAttributes) 在 Microsoft.Maui.Controls.BindingExpression.ApplyCore(对象源对象,BindableObject 目标,BindableProperty 属性,布尔值 fromTarget) 在 Microsoft.Maui.Controls.BindingExpression.Apply(对象源对象、BindableObject 目标、BindableProperty 属性) 在 Microsoft.Maui.Controls.Binding.d__27.MoveNext() 在 System.Threading.Tasks.Task.<>c.b__128_0(对象状态) 在 Microsoft.UI.Dispatching.DispatcherQueueSynchronizationContext.<>c__DisplayClass2_0.b__0() --- 先前位置的堆栈跟踪结束 --- 在 WinRT.ExceptionHelpers.g__Throw|20_0(Int32 小时) 在 ABI.Windows.ApplicationModel.Core.IUnhandledErrorMethods.Propagate(IObjectReference _obj) 在 Windows.ApplicationModel.Core.UnhandledError.Propagate() 在 Microsoft.AppCenter.Utils.ApplicationLifecycleHelperWinUI。<.ctor>b__0_3(对象发送者,UnhandledErrorDetectedEventArgs eventArgs) --- 先前位置的堆栈跟踪结束 --- 在 Microsoft.AppCenter.Utils.ApplicationLifecycleHelperWinUI。<.ctor>b__0_3(对象发送者,UnhandledErrorDetectedEventArgs eventArgs) 在 WinRT.EventSource__EventHandler
1.EventState.<GetEventInvoke>b__1_0(Object obj, T e) at ABI.System.EventHandler
1.Do_Abi_Invoke[TAbi](Void* thisPtr, IntPtr 发送者, TAbi args)

c# uicollectionview maui controltemplate contentpresenter
1个回答
0
投票

请勿将标签放入

uc:ListViewsTemplate
:

<uc:ListViewsTemplate ItemsSource="{Binding Items}" ItemTapped="{Binding ItemTappedCommand}" VerticalOptions="StartAndExpand" >
            <!--<Label BindingContext="{Binding Source={RelativeSource AncestorType={x:Type model:ListViewsTemplateModel}}}"
               x:DataType="{x:Type model:ListViewsTemplateModel}"
               Text="{Binding Name}" />-->
</uc:ListViewsTemplate>

因为这样你创建的ContentView(ListViewsTemplate)就失去了意义。所以,把它放进

ListViewsTemplate

.....
<DataTemplate>
    <Grid>
        <Frame>
            <Frame.GestureRecognizers>
                <TapGestureRecognizer Command="{TemplateBinding ItemTapped}" 
                                      CommandParameter="{Binding .}" />
            </Frame.GestureRecognizers>

            <!-- Put it here or anywhere else you like -->
            <Label x:DataType="{x:Type model:ListViewsTemplateModel}" 
                   Text="{Binding Name}" />
        </Frame>
        <Rectangle IsVisible="{OnPlatform false, Android=True}" HeightRequest="2" Fill="Black"/>
    </Grid>
</DataTemplate>
.....

我测试过,效果很好。

© www.soinside.com 2019 - 2024. All rights reserved.