由于 XamlC 错误 XFC0045,无法编译和运行 .net 8 MAUI 应用程序:绑定:在视图模型上找不到属性“名称”

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

出于某种原因,当在父 CollectionView 中使用 ItemsSource="{Binding Patient}" 和嵌套 CollectionView 与 ItemsSource="{Binding Visits}" 进行数据竞价时,出现错误

在嵌套 CollectionView 的 DataTemplate 中,我具有绑定的 FolderItem 属性,如 IsFolder、Name 和 IsExpanded。当我使用 Visual Studio 2022 并打开此 Maui 8 应用程序和页面:MyLibraryPage.xaml 时,我可以单击这些绑定的属性名称并按 F8,它将带我到访客属性集合项的相应属性:FolderItem 我收到这个消息,这阻止我正确编译代码并运行它。

MyLibraryPage.xaml(47,15):XamlC 错误 XFC0045:绑定:在“Demo.ViewModels.MyLibraryPageViewModel”上找不到属性“名称”。

如果我评论这一行,不同的绑定会出现相同的错误。

<?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:viewmodels="clr-namespace:Plugin.Maui.Audio.Sample.ViewModels"
             xmlns:converters="clr-namespace:Plugin.Maui.Audio.Sample.Converters"
             x:Class="Plugin.Maui.Audio.Sample.Pages.MyLibraryPage"
             Title="My Library"
             x:Name="Page"
             x:DataType="viewmodels:MyLibraryPageViewModel">

    <ContentPage.Resources>
        <Style x:Key="border_gallery_card" TargetType="Border">
            <Setter Property="Stroke" Value="{AppThemeBinding Light={StaticResource Gray200}, Dark={StaticResource Gray950}}" />
            <Setter Property="BackgroundColor" Value="{AppThemeBinding Light={StaticResource White}, Dark={StaticResource Gray950}}" />
            <Setter Property="Padding" Value="16" />
            <Setter Property="StrokeThickness" Value="1" />
            <Setter Property="StrokeShape" Value="RoundRectangle 8" />
        </Style>

        <converters:FolderFileIconConverter x:Key="FolderFileIconConverter" />
        <converters:FolderFileFontAttributeConverter x:Key="FolderFileFontAttributeConverter" />
        <converters:ExpandCollapseConverter x:Key="ExpandCollapseConverter" />

        <!-- Font attributes as resources -->
        <FontAttributes x:Key="BoldFontAttribute">Bold</FontAttributes>
        <FontAttributes x:Key="NoneFontAttribute">None</FontAttributes>

        <!-- Icons -->
        <FontImageSource x:Key="PersonIcon" Glyph="&#xf007;" FontFamily="FontAwesome" Size="20" />
        <FontImageSource x:Key="FolderIcon" Glyph="&#xf07b;" FontFamily="FontAwesome" Size="20" />
        <FontImageSource x:Key="FileIcon" Glyph="&#xf15b;" FontFamily="FontAwesome" Size="20" />
        <FontImageSource x:Key="ExpandIcon" Glyph="&#xf067;" FontFamily="FontAwesome" Size="20" />
        <FontImageSource x:Key="CollapseIcon" Glyph="&#xf068;" FontFamily="FontAwesome" Size="20" />
    </ContentPage.Resources>

    <Grid RowDefinitions="60,*,150">
        <Grid ColumnDefinitions="*,Auto">
            <Entry x:Name="PatientIdEntry" Placeholder="Enter Patient ID" Grid.Column="0" />
            <Button Text="Create Recording" Grid.Column="1" Command="{Binding AddRecordingCommand}" />
        </Grid>
        <CollectionView x:Name="FilesCollectionView" ItemsSource="{Binding Patients}" SelectionMode="Single" Grid.Row="1">
            <CollectionView.ItemTemplate>
                <DataTemplate>
                    <StackLayout>
                        <Grid ColumnDefinitions="Auto, *, Auto">
                            <Image Source="{StaticResource PersonIcon}" VerticalOptions="Center" />
                            <Label Text="{Binding Name}" FontAttributes="Bold" VerticalOptions="Center" />
                            <ImageButton Source="{Binding IsExpanded, Converter={StaticResource ExpandCollapseConverter}}" Command="{Binding Path=BindingContext.OpenMusicCommand, Source={x:Reference Page}}" CommandParameter="{Binding .}" />
                        </Grid>
                        <CollectionView ItemsSource="{Binding Visits}" IsVisible="{Binding IsExpanded}" SelectionMode="Single">
                            <CollectionView.ItemTemplate>
                                <DataTemplate>
                                    <StackLayout Padding="20,0,0,0">
                                        <Grid ColumnDefinitions="Auto, *, Auto">
                                            <Image Source="{Binding IsFolder, Converter={StaticResource FolderFileIconConverter}}" VerticalOptions="Center" />
                                            <Label Text="{Binding Name}" FontAttributes="{Binding IsFolder, Converter={StaticResource FolderFileFontAttributeConverter}}" VerticalOptions="Center" />
                                            <ImageButton Source="{Binding IsExpanded, Converter={StaticResource ExpandCollapseConverter}}" Command="{Binding Path=BindingContext.OpenMusicCommand, Source={x:Reference Page}}" CommandParameter="{Binding .}" />
                                        </Grid>
                                        <CollectionView ItemsSource="{Binding Children}" IsVisible="{Binding IsExpanded}" SelectionMode="Single">
                                            <CollectionView.ItemTemplate>
                                                <DataTemplate>
                                                    <StackLayout Padding="20,0,0,0">
                                                        <Border Style="{StaticResource border_gallery_card}">
                                                            <Border.GestureRecognizers>
                                                                <TapGestureRecognizer Command="{Binding Path=BindingContext.OpenMusicCommand, Source={x:Reference Page}}" CommandParameter="{Binding .}" />
                                                            </Border.GestureRecognizers>
                                                            <Label Text="{Binding Name}" />
                                                        </Border>
                                                    </StackLayout>
                                                </DataTemplate>
                                            </CollectionView.ItemTemplate>
                                        </CollectionView>
                                    </StackLayout>
                                </DataTemplate>
                            </CollectionView.ItemTemplate>
                        </CollectionView>
                    </StackLayout>
                </DataTemplate>
            </CollectionView.ItemTemplate>
        </CollectionView>

        <!-- Patient Details Section -->
        <StackLayout Grid.Row="2" Padding="10">
            <Label Text="Patient Details" FontAttributes="Bold" FontSize="Medium" />
            <Image Source="{Binding SelectedPatient.PictureUrl}" HeightRequest="100" WidthRequest="100" />
            <Label Text="Name: " />
            <Label Text="{Binding SelectedPatient.Name}" />
            <Label Text="Health Card Number: " />
            <Label Text="{Binding SelectedPatient.HealthCardNumber}" />
            <Label Text="Last Visit: " />
            <Label Text="{Binding SelectedPatient.LastVisitDateTime}" />
            <Label Text="Length of Visit: " />
            <Label Text="{Binding SelectedPatient.LengthOfVisit}" />
        </StackLayout>
    </Grid>
</ContentPage>

Pages\MyLibraryPage.xaml.cs
---------------------------------------
using Plugin.Maui.Audio.Sample.ViewModels;

namespace Plugin.Maui.Audio.Sample.Pages;

public partial class MyLibraryPage : ContentPage
{
    public MyLibraryPage(MyLibraryPageViewModel myLibraryPageViewModel)
    {
        InitializeComponent();

        BindingContext = myLibraryPageViewModel;
    }
}


ViewModels\Patient.cs
------------------------------------------
using System.Collections.ObjectModel;

namespace Plugin.Maui.Audio.Sample.ViewModels;

public class Patient : BaseViewModel
{
    bool isExpanded;
    public string PatientId { get; set; }
    public string Name { get; set; }
    public string PictureUrl { get; set; }
    public string HealthCardNumber { get; set; }
    public DateTime LastVisitDateTime { get; set; }
    public string LengthOfVisit { get; set; }
    public ObservableCollection<FolderItem> Visits { get; set; }

    public bool IsExpanded
    {
        get => isExpanded;
        set
        {
            isExpanded = value;
            NotifyPropertyChanged();
        }
    }

    public Patient()
    {
        Visits = new ObservableCollection<FolderItem>();
    }
}

ViewModels\FolderItem.cs
-----------------------------------
using System.Collections.ObjectModel;

namespace Plugin.Maui.Audio.Sample.ViewModels;

public class FolderItem : BaseViewModel
{
    bool isExpanded;

    public string Name { get; set; }
    public bool IsFolder { get; set; }
    public ObservableCollection<FolderItem> Children { get; set; }
    public bool IsExpanded
    {
        get => isExpanded;
        set
        {
            isExpanded = value;
            NotifyPropertyChanged();
        }
    }

    public FolderItem()
    {
        Children = new ObservableCollection<FolderItem>();
    }
}

ViewModels\MyLibraryPageViewModel.cs
--------------------------------------------
using System.Collections.ObjectModel;

namespace Plugin.Maui.Audio.Sample.ViewModels;
public class MyLibraryPageViewModel : BaseViewModel
{
    public Command AddRecordingCommand { get; }
    public Command<FolderItem> OpenMusicCommand { get; }

    ObservableCollection<Patient> patients;
    Patient selectedPatient;

    public ObservableCollection<Patient> Patients
    {
        get => patients;
        set
        {
            patients = value;
            NotifyPropertyChanged();
        }
    }
    public Patient SelectedPatient
    {
        get => selectedPatient;
        set
        {
            selectedPatient = value;
            NotifyPropertyChanged();
        }
    }

    public MyLibraryPageViewModel()
    {
         Patients = new ObservableCollection<Patient>
         {
            new Patient
            {
                PatientId = "100",
                Name = "John Doe",
                Visits = new ObservableCollection<FolderItem>
                {
                    new FolderItem
                    {
                        Name = "2023-09-22",
                        IsFolder = true,
                        Children = new ObservableCollection<FolderItem>
                        {
                            new FolderItem
                            {
                                Name = "100_2023-09-22_10-30-00.mp3",
                                IsFolder = false
                            },
                            new FolderItem
                            {
                                Name = "100_2023-09-22_11-00-00.mp3",
                                IsFolder = false
                            }
                        }
                    },
                    new FolderItem 
                    { 
                        Name = "2023-09-21", 
                        IsFolder = true,
                        Children = new ObservableCollection<FolderItem>
                        {
                            new FolderItem
                            {
                                Name = "100_2023-09-21_13-30-00.mp3",
                                IsFolder = false
                            },
                            new FolderItem
                            {
                                Name = "100_2023-09-22_11-00-00.mp3",
                                IsFolder = false
                            }
                        }
                    }
                }
            }
        };

        AddRecordingCommand = new Command(async () => await AddRecording());
        OpenMusicCommand = new Command<FolderItem>(async (item) => await OnMusicItemSelected(item));
    }

    static async Task AddRecording()
    {
        await Shell.Current.GoToAsync("AudioRecorderPage");
    }

    static async Task OnMusicItemSelected(FolderItem item)
    {
        if (item.IsFolder)
        {
            item.IsExpanded = !item.IsExpanded;
        }
        else
        {
            await Shell.Current.GoToAsync(
                "MusicPlayerPage",
                new Dictionary<string, object>
                {
                    ["Music"] = item
                });
        }
    }
}

.net binding maui
1个回答
0
投票

当您将 CollectionView 嵌套在另一个 CollectionView 中时,内部 CollectionView 的绑定上下文将成为外部 CollectionView 的当前项。因此,您需要确保嵌套 CollectionView 的 DataTemplate 已正确设置为正确的上下文。

要解决此问题,您应该将嵌套 CollectionView 的绑定上下文设置为适当的数据类型。这是 XAML 的更新版本,重点关注嵌套 CollectionView:

<CollectionView ItemsSource="{Binding Patients}">
        <CollectionView.ItemTemplate>
            <DataTemplate>
                <StackLayout>
                    <Label Text="{Binding Name}" /> <!-- Assuming Patients have a Name property -->
                    
                    <!-- Nested CollectionView for Visits -->
                    <CollectionView ItemsSource="{Binding Visits}">
                        <CollectionView.ItemTemplate>
                            <DataTemplate>
                                <StackLayout>
                                    <Label Text="{Binding Name}" />
                                    <Label Text="{Binding IsFolder}" />
                                    <Label Text="{Binding IsExpanded}" />
                                    <!-- Other properties of FolderItem -->
                                </StackLayout>
                            </DataTemplate>
                        </CollectionView.ItemTemplate>
                    </CollectionView>
                </StackLayout>
            </DataTemplate>
        </CollectionView.ItemTemplate>
    </CollectionView>
© www.soinside.com 2019 - 2024. All rights reserved.