在 ViewModel 上找不到绑定属性,即使它存在

yas*_*ana 0 .net compiled-bindings maui

我创建了一个名为 的模型类Project,还创建了一个名为 的 ViewModel 类MainPageViewModel

我想要实现的是一个具有多列的简单表。应该有一个名为“操作”的列,并且该列应该有一个按钮。

这是 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"
             x:Class="SharpTool.UI.MainPage"
             xmlns:viewmodel="clr-namespace:SharpTool.UI.ViewModels"
             xmlns:models ="clr-namespace:SharpTool.UI.Models"
             x:DataType="viewmodel:MainPageViewModel">
    
    <ScrollView>
        <VerticalStackLayout
            Padding="10, 10">
            <Border MinimumHeightRequest="50" StrokeThickness ="0.5">
    
                <Grid>
                    <Grid.ColumnDefinitions>
                        <ColumnDefinition Width="*" />
                        <ColumnDefinition Width="*"/>
                        <ColumnDefinition Width="*"/>
                        <ColumnDefinition Width="*"/>
                        <ColumnDefinition Width="*"/>
                    </Grid.ColumnDefinitions>
    
                    <Border StrokeThickness="0.1" Grid.Column="0">
                        <Label HorizontalOptions="Center" VerticalOptions="Center" FontFamily="icon" FontSize="15" Text="Id" TextColor="Blue"/>
                    </Border>
    
                    <Border StrokeThickness="0.1" Grid.Column="1">
                        <Label HorizontalOptions="Center" VerticalOptions="Center" FontFamily="icon" FontSize="15" Text="Name" TextColor="Blue"/>
                    </Border>
    
                    <Border StrokeThickness="0.1"  Grid.Column="2">
                        <Label HorizontalOptions="Center" VerticalOptions="Center" FontFamily="icon" FontSize="15" Text="Discription" TextColor="Blue"/>
                    </Border>
    
                    <Border StrokeThickness="0.1" Grid.Column="3">
                        <Label HorizontalOptions="Center" VerticalOptions="Center" FontFamily="icon" FontSize="15" Text="Version" TextColor="Blue"/>
                    </Border>
                        
                    <Border StrokeThickness="0.1" Grid.Column="4">
                        <Label HorizontalOptions="Center" VerticalOptions="Center" FontFamily="icon" FontSize="15" Text="Action" TextColor="Blue"/>
                    </Border>
    
                </Grid>
    
            </Border>
    
            <CollectionView ItemsSource="{Binding Projects}" >
    
                <CollectionView.ItemsLayout>
                    <LinearItemsLayout Orientation="Vertical"/>
                </CollectionView.ItemsLayout>
    
                <CollectionView.ItemTemplate>
                    <DataTemplate x:DataType="models:Project">
    
                        <Border MinimumHeightRequest="50" StrokeThickness ="0.5" >
    
                            <Grid>
                                <Grid.ColumnDefinitions>
                                    <ColumnDefinition Width="*" />
                                    <ColumnDefinition Width="*"/>
                                    <ColumnDefinition Width="*"/>
                                    <ColumnDefinition Width="*"/>
                                    <ColumnDefinition Width="*"/>
                                </Grid.ColumnDefinitions>
    
                                <Border StrokeThickness="0.1" Grid.Column="0">
                                    <Label HorizontalOptions="Center" VerticalOptions="Center" FontFamily="icon" FontSize="15" Text="{Binding Id}" TextColor="Blue"/>
                                </Border>
    
                                <Border StrokeThickness="0.1" Grid.Column="1">
                                    <Label HorizontalOptions="Center" VerticalOptions="Center" FontFamily="icon" FontSize="15" Text="{Binding Name}" TextColor="Blue"/>
                                </Border>
    
                                <Border StrokeThickness="0.1"  Grid.Column="2">
                                    <Label HorizontalOptions="Center" VerticalOptions="Center" FontFamily="icon" FontSize="15" Text="{Binding Description}"  TextColor="Blue"/>
                                </Border>
    
                                <Border StrokeThickness="0.1" Grid.Column="3">
                                    <Label HorizontalOptions="Center" VerticalOptions="Center" FontFamily="icon" FontSize="15" Text="{Binding Version}" TextColor="Blue"/>
                                </Border>
    
                                <Border StrokeThickness="0.1" Grid.Column="4">
    
                                    <Button
                                        Text="Click me"
                                        SemanticProperties.Hint="Counts the number of times you click"
                                        Command="{Binding GetProjectByCommand}"
                                        CommandParameter="2"
                                        HorizontalOptions="Center" />
                                </Border>
    
                            </Grid>
    
                        </Border>
    
                    </DataTemplate>
    
                </CollectionView.ItemTemplate>
            </CollectionView>
    
        </VerticalStackLayout>
    </ScrollView>
    
</ContentPage>
Run Code Online (Sandbox Code Playgroud)

我设法实现了 UI 代码,但遇到了问题。当我设置 时x:DataType="models:Project"DataTemplate我无法将 ViewModel 方法绑定到按钮或任何其他组件。

它给了我一个错误:

绑定:在“SharpTool.UI.Models.Project”上找不到属性“GetProjectByCommand”。

如果我删除这部分: Command="{Binding GetProjectByCommand}"在 内的按钮中Grid,那么项目将构建并运行,不会出现任何问题。

这是视图模型代码:

[INotifyPropertyChanged]
public partial class MainPageViewModel
{
    [ObservableProperty]
    ObservableCollection<Project> projects = new();
    
    [ObservableProperty]
    public bool isBusy = false;
    
    public ICommand GetProjectByCommand { private set; get; }
    
    public MainPageViewModel()
    {
        projects.Add(new Project { Id = 1, Name = "Project 1 Name", Description = "Project 1 Description", Version = "1.0" });
        projects.Add(new Project { Id = 2, Name = "Project 2 Name", Description = "Project 2 Description", Version = "1.0" });
        projects.Add(new Project { Id = 3, Name = "Project 3 Name", Description = "Project 3 Description", Version = "1.0" });
        projects.Add(new Project { Id = 4, Name = "Project 1 Name", Description = "Project 1 Description", Version = "1.0" });
        projects.Add(new Project { Id = 5, Name = "Project 2 Name", Description = "Project 2 Description", Version = "1.0" });
        projects.Add(new Project { Id = 6, Name = "Project 3 Name", Description = "Project 3 Description", Version = "1.0" });
        projects.Add(new Project { Id = 7, Name = "Project 1 Name", Description = "Project 1 Description", Version = "1.0" });
        projects.Add(new Project { Id = 8, Name = "Project 2 Name", Description = "Project 2 Description", Version = "1.0" });
        projects.Add(new Project { Id = 9, Name = "Project 3 Name", Description = "Project 3 Description", Version = "1.0" });
        projects.Add(new Project { Id = 10, Name = "Project 3 Name", Description = "Project 3 Description", Version = "1.0" });
    
        GetProjectByCommand = new Command<string>(GetProjectById);
    }
    
    private void GetProjectById(string id)
    {
        //query project list
    }
}
Run Code Online (Sandbox Code Playgroud)

那么,如何将该GetProjectById方法绑定到网格内的按钮?

Ger*_*uis 5

这种事经常发生。这里的问题是,每当您处于显示项目的控件中时,数据绑定范围都会发生变化。

对于您的整页,视图模型是您的MainPageViewModel. 然后你就有了一个从你的属性CollectionView中读取的内容。到目前为止,一切都很好。ProjectsMainPageViewModel

但是,在您的内部CollectionView,尤其是在您的内部ItemTemplate,您的范围不再局限于页面的其余部分,但绑定上下文现在是您在其中放置的任何项目的类型(在您的情况下)Project。您还可以看到这一点,因为您必须指定<DataTemplate x:DataType="models:Project">哪个应该向您表明您现在正在查看Project对象,而不是不再查看对象MainPageViewModel

有多种选择可以解决这个问题。最明显但不一定最好的是将 添加GetProjectByCommand到您的Project对象中。然而,从技术上讲,这可能是您的责任MainPageViewModel

另一个选择是更改您的绑定以确保它MainPageViewModel再次查看您的。为此,请更改此行:

<Button
    Text="Click me"
    SemanticProperties.Hint="Counts the number of times you click"
    Command="{Binding GetProjectByCommand}"
    CommandParameter="2"
    HorizontalOptions="Center" />
Run Code Online (Sandbox Code Playgroud)

对此:

<Button
    Text="Click me"
    SemanticProperties.Hint="Counts the number of times you click"
    Command="{Binding GetProjectByCommand, Source={x:Reference mainPage.BindingContext}}"
    CommandParameter="2"
    HorizontalOptions="Center" />
Run Code Online (Sandbox Code Playgroud)

为了使其正常工作,请确保将该x:Name="mainPage"属性添加到您的ContentPage节点。

其作用是将绑定的源设置为mainPage.BindingContext您的MainPageViewModel.

有关此内容的更多信息也可以在我的视频中找到:https://www.youtube.com/watch ?v=Or_qn8i8jVM

我刚刚注意到在我的视频中我使用了不同的语法:

<Button
    Text="Click me"
    SemanticProperties.Hint="Counts the number of times you click"
    Command="{Binding Path=BindingContext.GetProjectByCommand, Source={Reference mainPage}}"
    CommandParameter="2"
    HorizontalOptions="Center" />
Run Code Online (Sandbox Code Playgroud)

本质上是相同的,但写法不同。