我正在尝试在毛伊岛创建一个母版/详细信息页面。就像带有发票项目的发票一样,此页面必须显示多个“发票”,每个发票都有自己的发票项目。
假设我们有一张发票清单。每张发票在 SQL Server 中都有两个关联的表(标题和项目)。
我将这些表中的每一个都拉到一组类中——一个数组用于发票标题,一个用于发票项目。
我需要显示所有发票的滚动列表。因此该页面将显示 Invoice Header #1 和与该 invId 关联的项目,
然后显示发票抬头 #2 - 以及与该发票关联的发票项目。
发票项目必须特定于所显示的发票 - 目前我在这方面失败得很严重?
它 .. 几乎 .. 可以工作,因为我可以在每个 InvHeader 下的嵌套网格中显示所有 InvItems,但我不能将它们限制为仅显示 InvItems,其中 InvHeader.CustId = InvItem.CustId.
如果我可以将参数发送到 InvItemsForCustIdConverter,那么我就完成了。
它只需要 InvHeader.CustId 用于嵌套 InvItems StackLayout 的 StackLayout。
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage x:Name="parentView"
xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:converters="clr-namespace:MauiClient"
x:Class="MauiClient.Invoice"
Title="Invoice">
<ContentPage.Resources>
<ResourceDictionary>
<converters:InvItemsForCustIdConverter x:Key="InvItemsForCustIdConverter" />
</ResourceDictionary>
</ContentPage.Resources>
<ScrollView>
<StackLayout>
<!-- Header section -->
<Label Text="Hospitals" FontSize="Title" />
<CollectionView ItemsSource="{Binding invHeaders}" BackgroundColor="Blue">
<CollectionView.ItemTemplate>
<DataTemplate>
<StackLayout>
<Label Text="{Binding Company}" />
<Label Text="{Binding Addr1}" />
<Label Text="{Binding Phone}" />
<Label Text="{Binding CustId}" BackgroundColor="Red" TextColor="White" />
<!-- Invoice items section -->
<Label Text="Tech Times" FontSize="Title" BackgroundColor="Yellow" TextColor="Black"/>
<StackLayout BindingContext="{Binding BindingContext, Source={x:Reference parentView}}" BackgroundColor="Green">
<StackLayout BindableLayout.ItemsSource="{Binding InvItems, Converter={StaticResource InvItemsForCustIdConverter}, ConverterParameter={Binding CustId}}">
<BindableLayout.ItemTemplate>
<DataTemplate>
<StackLayout Orientation="Horizontal" Spacing="20">
<Label Text="{Binding ItemId}" />
<Label Text="{Binding CustId}" BackgroundColor="Red" TextColor="White" />
</StackLayout>
</DataTemplate>
</BindableLayout.ItemTemplate>
</StackLayout>
</StackLayout>
</StackLayout>
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
</StackLayout>
</ScrollView>
</ContentPage>
public class InvoiceViewModel {
public List<InvHeader> InvHeaders { get; set; }
public List<InvItem> InvItems { get; set; }
}
// changing ConverterParameter={Binding CustId}}"> to ConverterParameter={Binding InvHeader.CustId}}">
// just changes the PATH in parameter to PATH InvHeader.CustId
// we are always passing null??
// value shows as 39 InvItems
// trying a few variations, all of them return null in parameter
// <StackLayout BindableLayout.ItemsSource="{Binding InvItems, Converter={StaticResource InvItemsForCustIdConverter}, ConverterParameter={Binding InvHeader.CustId}}">
// <StackLayout BindableLayout.ItemsSource="{Binding InvItems, Converter={StaticResource InvItemsForCustIdConverter}, ConverterParameter={Binding CustId}}">
// <StackLayout BindableLayout.ItemsSource="{Binding InvItems, Converter={StaticResource InvItemsForCustIdConverter}, ConverterParameter={Binding CustId, Source={x:Reference parentView}, Path=InvHeader}}">
public class InvItemsForCustIdConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
return value; // If I return the invItems then the display works, but does not Limit the InvItems to those matching the InvHeader StackLayout
if (value is List<InvItem> invItems && parameter is string custId)
{
return invItems.Where(x => x.CustId == custId).ToList();
}
return null;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
我需要显示所有发票的滚动列表。所以页面会 显示 Invoice Header #1 和与该 invId 关联的项目。
我建议你可以使用SQL从两个表中查询你想要的数据,而不是使用
ConverterParameter
在代码隐藏中编写逻辑代码。
如果要在code-behind中处理数据,可以将两个表的数据分别放入两个列表中,每个列表都有自己的实体,这样就可以更方便地处理数据。
我在另一个 StackOverlow 线程中使用修改后的代码以不同的方式处理了这个问题,并收到了一个很好的建议以及来自 Jessie Zhang -MSFT 的几乎可以工作的代码。
我没有使用他的 TempInvItems 列表,而是只使用了一个 InvItems 列表,该列表针对每个 InvHeader 列表项进行了过滤,如下所示:
foreach (var wsc in InvHeaders)
{
wsc.InvItems = InvItems.Where(x => x.CustId == wsc.CustId).ToList();
}
代码完美运行!
Jessie Zhang -MSFT 的解决方案链接在这里: 在显示之前过滤 InvItems