在嵌套的 StackLayout 中使用 Maui XAML 绑定 InvHeader/InvItems,其中 InvHeader.CustId = InvItem.CustId?

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

我正在尝试在毛伊岛创建一个母版/详细信息页面。就像带有发票项目的发票一样,此页面必须显示多个“发票”,每个发票都有自己的发票项目。

假设我们有一张发票清单。每张发票在 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();
  }
}

c# xaml data-binding maui code-behind
2个回答
0
投票

我需要显示所有发票的滚动列表。所以页面会 显示 Invoice Header #1 和与该 invId 关联的项目。

我建议你可以使用SQL从两个表中查询你想要的数据,而不是使用

ConverterParameter
在代码隐藏中编写逻辑代码。

如果要在code-behind中处理数据,可以将两个表的数据分别放入两个列表中,每个列表都有自己的实体,这样就可以更方便地处理数据。


0
投票

我在另一个 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

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