XAML、绑定、源和路径



我正在学习理解。net MAUI的XAML绑定机制是如何工作的。我假设这对于所有XAML项目,WPF, MAUI等都是相同的。

最后是整个XAML。

这个XAML工作得很好:

<Button WidthRequest="150" Text="Add Activity" 
Command="{Binding AddActivityEntityCommand}"
IsEnabled="{Binding IsNotBusy}"
Grid.Row="2"
Margin="8"/>
  • 这是因为按钮是ContentPage的一部分,它的x:DataType设置为MainPageViewModel,这是命令生活的地方吗?

  • 绑定设置为AddActivityEntityCommand,实际方法签名为
    async Task AddActivityEntityAsync()。如何解决这个问题?因为它显然与名字不匹配,但它有效。要使其工作/被识别,方法签名要求是什么?

另一方面,这并不像开箱即用那样容易:

<Label HorizontalOptions="End" TextColor="Red" Padding="0,0,10,0" Text="🗑" 
IsVisible="{Binding IsSynchronized}">
<Label.GestureRecognizers>
<TapGestureRecognizer 
Command="{Binding Source={x:Type viewmodel:MainPageViewModel},
Path=DeleteActivityCommand}" />
</Label.GestureRecognizers>
</Label>
  • 在这种情况下,添加Command="{Binding DeleteActivityCommand}不起作用,因为它从<DataTemplate x:DataType="model:ActivityEntity">派生其路径,我假设,这是数据对象而不是ViewModel,命令实际上在哪里。
  • 这里的问题是,只要我进入这个XAMLCommand="{Binding Source={x:Type viewmodel:MainPageViewModel}, Path=DeleteActivityCommand}", CollectionView显示为空,并且在加载视图时抛出一个未处理的异常:

System.Reflection。TargetException: Object does not match target type.

  • 此命令的方法签名为async Task DeleteActivityAsync()

我错过了什么?

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage
x:Class="OnesieMobile.View.MainPage"
xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:model="clr-namespace:OnesieMobile.Model"
xmlns:viewmodel="clr-namespace:OnesieMobile.ViewModel"
x:DataType="viewmodel:MainPageViewModel"
Title="{Binding Title}">
<Grid
ColumnDefinitions="*"
RowDefinitions="20,50,50,*"
RowSpacing="0">
<Label HorizontalOptions="End" Margin="10,0,10,0"  Text="{Binding CurrentDateTime}" Grid.Row="0"/>
<Entry Margin="10,0,10,0" 
Grid.Row="1"  x:Name="entryNewActivity" 
Placeholder="New Activityssss" HeightRequest="30" Text="{Binding NewActivityTitle}" />
<Button WidthRequest="150" Text="Add Activity" 
Command="{Binding AddActivityEntityCommand}"
IsEnabled="{Binding IsNotBusy}"
Grid.Row="2"
Margin="8"/>
<CollectionView
Grid.Row="3"
ItemsSource="{Binding ActivityEntities}"
SelectionMode="None">
<CollectionView.ItemTemplate>
<DataTemplate x:DataType="model:ActivityEntity">
<Grid Padding="10,0,10,0">
<Frame Style="{StaticResource CardView}">
<Grid  ColumnDefinitions="*,30,50">
<StackLayout Padding="10,5,0,0" Grid.Column="0">
<Label Text="{Binding Title}"  />
</StackLayout>
<StackLayout Padding="10,5,0,0" Grid.Column="1">
<Label HorizontalOptions="End" TextColor="Red"
Padding="0,0,10,0" Text="🗑" IsVisible="{Binding IsSynchronized}"  >
<Label.GestureRecognizers>
<TapGestureRecognizer
Command="{Binding Source={x:Type viewmodel:MainPageViewModel},
Path=DeleteActivityCommand}" />
</Label.GestureRecognizers>
</Label>
</StackLayout>
<StackLayout Padding="10,5,0,0" Grid.Column="2">
<Label HorizontalOptions="End" 
Padding="0,0,10,0" Text="✔" IsVisible="{Binding IsSynchronized}"  />
</StackLayout>
</Grid>
</Frame>
</Grid>
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
<ActivityIndicator IsVisible="{Binding IsBusy}"
IsRunning="{Binding IsBusy}"
HorizontalOptions="FillAndExpand"
VerticalOptions="CenterAndExpand"
Grid.RowSpan="3"
Grid.ColumnSpan="2"/>
</Grid>
</ContentPage>

更新:
MainPageViewModel.cs包含以下命令

[ICommand]
async Task DeleteActivityAsync()
{
}

[ICommand]
async Task AddActivityEntityAsync()
{
}

在项模板中,有几种方法可以引用原始的BindingContext。我喜欢从集合本身获取它:

<CollectionView x:Name="myCollection" ...>
...
<CollectionView.ItemTemplate>
...
Command="{Binding Source={x:Reference myCollection},
Path=BindingContext.DeleteActivityCommand}" />
未来TBD:

我不喜欢命令名在实现代码的任何地方都不存在。希望最终会有一种方法可以在ICommand属性中指定命令名称,以使其明显:

// This won't work today.
[ICommand Name="DeleteActivityCommand"]
...

现在,我们必须学习[ICommand]的神奇命名规则,它似乎是"从结束删除Async(如果存在);将Command添加到end"

相关内容

  • 没有找到相关文章

最新更新