XAML 如何为嵌套的堆栈布局智能地创建和调试复杂的Maui数据绑定?

xtupzzrd  于 2023-04-27  发布在  其他
关注(0)|答案(1)|浏览(155)

我一直在尝试创建一个数据绑定,它可以从父堆栈布局中访问一个值。
我创建了一个转换器,认为这将给予我一些可见性,我的绑定正在做什么。
然而,我只是得到一个空的参数值-我需要设置为父堆栈布局中的字段的文本值?
必须有一些技术来智能地调试绑定,并了解如何创建正确的绑定?
我试着创建一个标签给予我一些线索,以什么样的约束力是做-尝试以下标签的许多变化,但..我已经很少成功?

<Label Text="{Binding Source={x:Reference parentView}, StringFormat='{0}'}" />

这是我的转换器,参数总是穆尔。

// 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();
  }
}

下面是我尝试调试的嵌套XAML

<?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" />
                                                <Label Text="{Binding Source={x:Reference parentView}, StringFormat='{0}'}" />
                                            </StackLayout>
                                        </DataTemplate>
                                    </BindableLayout.ItemTemplate>
                                </StackLayout>
                            </StackLayout>
                        </StackLayout>
                    </DataTemplate>
                </CollectionView.ItemTemplate>
            </CollectionView>
        </StackLayout>
    </ScrollView>
</ContentPage>

下面是基本的ViewModel:

public class InvoiceViewModel  {
        public List<InvHeader> InvHeaders { get; set; }
        public List<InvItem> InvItems { get; set; }
}
np8igboo

np8igboo1#

事实上,如果我们想显示过滤后的数据,我们通常在代码后面过滤数据,而不是在xaml上,这将导致代码效率的降低。
此外,根据UI显示,您可以重新设计数据结构。
例如,您可以创建数据结构并筛选所需数据,如下所示:

public class InvHeader 
{
    public string Company { get; set; }

    public string Addr1 { get; set; }

    public string Phone { get; set; }

    public int CustId { get; set; }

   // TempInvItems represents the raw data that came over
    public List<InvItem> TempInvItems { get; set;} = new List<InvItem>();

    //InvItems represents the filtered data by `CustId`
    public List<InvItem> InvItems { get; set; } = new List<InvItem>();

    public InvHeader(string Company, string Addr1, string Phone, int CustId, List<InvItem> TempInvItems) {

        this.Company = Company;
        this.Addr1 = Addr1;
        this.Phone = Phone;
        this.CustId = CustId;
        this.TempInvItems = TempInvItems;
        
        // we can filter data here
        this.InvItems = TempInvItems.Where(x => x.CustId == this.CustId).ToList();
    }
}

并且我已经实现了这个功能,可以参考下面的代码.

InvItem.cs

public class InvItem 
{
    public int ItemId { get; set; }

    public int CustId { get; set; }
}

TestViewModel.cs

public class TestViewModel 
{
    public List<InvHeader> InvHeaders { get; set; }
    public TestViewModel() {
        InvHeaders = new List<InvHeader>();

        List<InvItem> items = new List<InvItem>();
        items.Add(new InvItem { CustId = 001, ItemId = 111 });
        items.Add(new InvItem { CustId = 002, ItemId = 112 });
        items.Add(new InvItem { CustId = 003, ItemId = 113});
        items.Add(new InvItem { CustId = 001, ItemId = 100 });
        items.Add(new InvItem { CustId = 001, ItemId = 99 });

        InvHeader header1 = new InvHeader("Company1", "Addr1_1", "123456789",  001, items );
        InvHeader header2 = new InvHeader ( "Company2","Addr1_2", "123456789", 001, items );
        InvHeader header3 = new InvHeader ("Company3", "Addr1_3", "123456789", 001, items );

        InvHeaders.Add(header1);
        InvHeaders.Add(header2);
        InvHeaders.Add(header3);

    }
}

使用示例:

<?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="MauiStuGroupApp.Views.HeaderPage"
             xmlns:local="clr-namespace:MauiStuGroupApp.ViewModels"
             Title="HeaderPage">

    <ContentPage.BindingContext>
        <local:TestViewModel></local:TestViewModel>
    </ContentPage.BindingContext>
    <VerticalStackLayout>
        <!-- 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  >
                            <StackLayout BindableLayout.ItemsSource="{Binding InvItems}" BackgroundColor="Green">
                                <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>
    </VerticalStackLayout>
</ContentPage>

相关问题