【问题标题】:Scrolling, Collapsing and Expanding in .NET MAUI在 .NET MAUI 中滚动、折叠和展开
【发布时间】:2023-02-20 22:33:04
【问题描述】:

当将控件设置为可见/不可见时,我正在尝试为 UI 使用 VerticalStackLayout 自动调整(展开/折叠)。如果可能的话,我还没有想出如何在网格中做到这一点的方法。

VerticalStackLayout 的问题是它里面的 CollectionView 不滚动。另一个要求是页面不应整体滚动.只有一部分应该滚动。在本例中是 CollectionView。

周围有网格,它工作正常。集合视图滚动,而 UI 的其余部分保持固定。

<ContentPage>
    <Grid RowDefinitions="50,*">
        <Button Grid.Row="0" />
        <CollectionView />
    </Grid>
</ContentPage>

这个问题是,当按钮设置为不可见时,由于行是固定的,所以会有一个空白空间。

&lt;Grid RowDefinitions="*,*"&gt; 之类的东西也不起作用,因为这只会影响行的分布方式,但不会影响它们是否折叠。

下一个结构适用于折叠部分。当按钮不可见时,空间会自动填充以下元素。但是集合视图不滚动,因此集合视图中的所有项目都不可见。

<ContentPage>
    <VerticalStackLayout>
        <Button />
        <CollectionView />
    </VerticalStackLayout>
</ContentPage>

如何结合滚动和折叠这两个功能?

我也尝试过 FlexLayout

<FlexLayout Direction="Column"
                AlignItems="Center"
                JustifyContent="Start">
    <Button />
    <CollectionView />  
</FlexLayout>

但这似乎总是使用整个页面,因此如果它们不适合则挤压元素。如果我将 CollectionView 设置为 HeightRequest="100",那么我会得到想要的结果,除了 CollectionView 不再一直到底部并且在屏幕中间被切断。

正如某些文章中所建议的那样,HeightRequest="0.9*" 之类的百分比似乎不适用于 .NET MAUI。

我在这里研究了文档 https://learn.microsoft.com/en-us/dotnet/maui/user-interface/layouts/flexlayout 但我还没有找到问题的答案。

【问题讨论】:

  • 我用 VerticalStackLayout 做了一个测试,结果是“CollectionView”可以滚动,上面的空间没有折叠。
  • @JessieZhang-MSFT 只是为了澄清。从我得到的,你得到了 VerticalStackLayout 的倒置效果?如果是这样,您可以分享您的 xaml 以供我复制吗?

标签: xaml .net-maui


【解决方案1】:

更新

CollectionView 本身就是一个 scrollView。因此,如果我们在另一个 scrollView 中包含一个 scrollView。这可能会导致用户正确使用它的不良行为和复杂性。 您可以重新组织代码的层次结构并使用标题或补充视图。

在这里,我们可以在CollectionView中添加CollectionView.Header来实现这个。你可以参考下面的代码,我这边是正常的。

<?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="MonkeyBusiness.View.VerticalStackLayoutPage"
             xmlns:viewmodel="clr-namespace:MonkeyBusiness.ViewModel"
             x:DataType="viewmodel:VerticalStackLayoutViewModel"
             xmlns:model="clr-namespace:MonkeyBusiness.Model">

            
            <CollectionView ItemsSource="{Binding Monkeys}">
            <CollectionView.Header>
                <StackLayout BackgroundColor="LightGray">
                    <Label x:Name="lblCollapsable" 
                   Text="Click button to collapse this text.&#10;&#10;How can this view be adjusted to support scrolling only for the collection view and not for the whole page?" 
                   Margin="20,20,0,0" HorizontalOptions="Fill"  HeightRequest="80" />

                    <Button Text="Collapse content" x:Name="btnCollapse" Clicked="btnCollapse_Clicked" HorizontalOptions="Fill" HeightRequest="60" Margin="6" />
                </StackLayout>
            </CollectionView.Header>


            <CollectionView.ItemTemplate>
                    <DataTemplate x:DataType="model:Monkey">
                        <Grid Padding="10">
                            <Grid.RowDefinitions>
                                <RowDefinition Height="Auto" />
                                <RowDefinition Height="Auto" />
                            </Grid.RowDefinitions>
                            <Grid.ColumnDefinitions>
                                <ColumnDefinition Width="Auto" />
                                <ColumnDefinition Width="Auto" />
                            </Grid.ColumnDefinitions>
                            <Image Grid.RowSpan="2" 
                               Source="{Binding ImageUrl}" 
                               Aspect="AspectFill"
                               HeightRequest="60" 
                               WidthRequest="60" />
                            <Label Grid.Column="1" 
                               Text="{Binding Name}" 
                               FontAttributes="Bold" />
                            <Label Grid.Row="1"
                               Grid.Column="1" 
                               Text="{Binding Location}"
                               FontAttributes="Italic" 
                               VerticalOptions="End" />
                        </Grid>
                    </DataTemplate>
                </CollectionView.ItemTemplate>
            </CollectionView>

</ContentPage>

如果是这样,您可以分享您的 xaml 以供我复制吗?

您可以参考我使用的以下代码:

MainPage.xaml.cs

public partial class MainPage : ContentPage
{
    int count = 0;

    public MainPage()
    {
        InitializeComponent();

        BindingContext = new MyViewModel();
    }

    private void testbtn_Clicked(object sender, EventArgs e)
    {
        testbtn.IsVisible = !testbtn.IsVisible;

    }
}

我的视图模型.cs

class MyViewModel: INotifyPropertyChanged
{
    readonly IList<Monkey> source;

    public ObservableCollection<Monkey> Monkeys { get; private set; }


    public MyViewModel()
    {
        source = new List<Monkey>();
        CreateMonkeyCollection();

    }

    void CreateMonkeyCollection()
    {
        source.Add(new Monkey
        {
            Name = "Baboon",
            Location = "Africa & Asia",
            Details = "Baboons are African and Arabian Old World monkeys belonging to the genus Papio, part of the subfamily Cercopithecinae.",
            ImageUrl = "https://upload.wikimedia.org/wikipedia/commons/thumb/f/fc/Papio_anubis_%28Serengeti%2C_2009%29.jpg/200px-Papio_anubis_%28Serengeti%2C_2009%29.jpg"
        });

        source.Add(new Monkey
        {
            Name = "Capuchin Monkey",
            Location = "Central & South America",
            Details = "The capuchin monkeys are New World monkeys of the subfamily Cebinae. Prior to 2011, the subfamily contained only a single genus, Cebus.",
            ImageUrl = "https://upload.wikimedia.org/wikipedia/commons/thumb/4/40/Capuchin_Costa_Rica.jpg/200px-Capuchin_Costa_Rica.jpg"
        });

        source.Add(new Monkey
        {
            Name = "Blue Monkey",
            Location = "Central and East Africa",
            Details = "The blue monkey or diademed monkey is a species of Old World monkey native to Central and East Africa, ranging from the upper Congo River basin east to the East African Rift and south to northern Angola and Zambia",
            ImageUrl = "https://upload.wikimedia.org/wikipedia/commons/thumb/8/83/BlueMonkey.jpg/220px-BlueMonkey.jpg"
        });

        source.Add(new Monkey
        {
            Name = "Squirrel Monkey",
            Location = "Central & South America",
            Details = "The squirrel monkeys are the New World monkeys of the genus Saimiri. They are the only genus in the subfamily Saimirinae. The name of the genus Saimiri is of Tupi origin, and was also used as an English name by early researchers.",
            ImageUrl = "https://upload.wikimedia.org/wikipedia/commons/thumb/2/20/Saimiri_sciureus-1_Luc_Viatour.jpg/220px-Saimiri_sciureus-1_Luc_Viatour.jpg"
        });

        source.Add(new Monkey
        {
            Name = "Golden Lion Tamarin",
            Location = "Brazil",
            Details = "The golden lion tamarin also known as the golden marmoset, is a small New World monkey of the family Callitrichidae.",
            ImageUrl = "https://upload.wikimedia.org/wikipedia/commons/thumb/8/87/Golden_lion_tamarin_portrait3.jpg/220px-Golden_lion_tamarin_portrait3.jpg"
        });

        source.Add(new Monkey
        {
            Name = "Howler Monkey",
            Location = "South America",
            Details = "Howler monkeys are among the largest of the New World monkeys. Fifteen species are currently recognised. Previously classified in the family Cebidae, they are now placed in the family Atelidae.",
            ImageUrl = "https://upload.wikimedia.org/wikipedia/commons/thumb/0/0d/Alouatta_guariba.jpg/200px-Alouatta_guariba.jpg"
        });

        source.Add(new Monkey
        {
            Name = "Japanese Macaque",
            Location = "Japan",
            Details = "The Japanese macaque, is a terrestrial Old World monkey species native to Japan. They are also sometimes known as the snow monkey because they live in areas where snow covers the ground for months each",
            ImageUrl = "https://upload.wikimedia.org/wikipedia/commons/thumb/c/c1/Macaca_fuscata_fuscata1.jpg/220px-Macaca_fuscata_fuscata1.jpg"
        });

        source.Add(new Monkey
        {
            Name = "Mandrill",
            Location = "Southern Cameroon, Gabon, Equatorial Guinea, and Congo",
            Details = "The mandrill is a primate of the Old World monkey family, closely related to the baboons and even more closely to the drill. It is found in southern Cameroon, Gabon, Equatorial Guinea, and Congo.",
            ImageUrl = "https://upload.wikimedia.org/wikipedia/commons/thumb/7/75/Mandrill_at_san_francisco_zoo.jpg/220px-Mandrill_at_san_francisco_zoo.jpg"
        });

        source.Add(new Monkey
        {
            Name = "Proboscis Monkey",
            Location = "Borneo",
            Details = "The proboscis monkey or long-nosed monkey, known as the bekantan in Malay, is a reddish-brown arboreal Old World monkey that is endemic to the south-east Asian island of Borneo.",
            ImageUrl = "https://upload.wikimedia.org/wikipedia/commons/thumb/e/e5/Proboscis_Monkey_in_Borneo.jpg/250px-Proboscis_Monkey_in_Borneo.jpg"
        });

        source.Add(new Monkey
        {
            Name = "Red-shanked Douc",
            Location = "Vietnam, Laos",
            Details = "The red-shanked douc is a species of Old World monkey, among the most colourful of all primates. This monkey is sometimes called the "costumed ape" for its extravagant appearance. From its knees to its ankles it sports maroon-red "stockings", and it appears to wear white forearm length gloves. Its attire is finished with black hands and feet. The golden face is framed by a white ruff, which is considerably fluffier in males. The eyelids are a soft powder blue. The tail is white with a triangle of white hair at the base. Males of all ages have a white spot on both sides of the corners of the rump patch, and red and white genitals.",
            ImageUrl = "https://upload.wikimedia.org/wikipedia/commons/thumb/9/9f/Portrait_of_a_Douc.jpg/159px-Portrait_of_a_Douc.jpg"
        });

        source.Add(new Monkey
        {
            Name = "Gray-shanked Douc",
            Location = "Vietnam",
            Details = "The gray-shanked douc langur is a douc species native to the Vietnamese provinces of Quảng Nam, Quảng Ngãi, Bình Định, Kon Tum, and Gia Lai. The total population is estimated at 550 to 700 individuals. In 2016, Dr Benjamin Rawson, Country Director of Fauna & Flora International - Vietnam Programme, announced a discovery of an additional population of more than 500 individuals found in Central Vietnam, bringing the total population up to approximately 1000 individuals.",
            ImageUrl = "https://upload.wikimedia.org/wikipedia/commons/thumb/0/0b/Cuc.Phuong.Primate.Rehab.center.jpg/320px-Cuc.Phuong.Primate.Rehab.center.jpg"
        });

        source.Add(new Monkey
        {
            Name = "Golden Snub-nosed Monkey",
            Location = "China",
            Details = "The golden snub-nosed monkey is an Old World monkey in the Colobinae subfamily. It is endemic to a small area in temperate, mountainous forests of central and Southwest China. They inhabit these mountainous forests of Southwestern China at elevations of 1,500-3,400 m above sea level. The Chinese name is Sichuan golden hair monkey. It is also widely referred to as the Sichuan snub-nosed monkey. Of the three species of snub-nosed monkeys in China, the golden snub-nosed monkey is the most widely distributed throughout China.",
            ImageUrl = "https://upload.wikimedia.org/wikipedia/commons/thumb/c/c8/Golden_Snub-nosed_Monkeys%2C_Qinling_Mountains_-_China.jpg/165px-Golden_Snub-nosed_Monkeys%2C_Qinling_Mountains_-_China.jpg"
        });

        source.Add(new Monkey
        {
            Name = "Black Snub-nosed Monkey",
            Location = "China",
            Details = "The black snub-nosed monkey, also known as the Yunnan snub-nosed monkey, is an endangered species of primate in the family Cercopithecidae. It is endemic to China, where it is known to the locals as the Yunnan golden hair monkey and the black golden hair monkey. It is threatened by habitat loss. It was named after Bishop Félix Biet.",
            ImageUrl = "https://upload.wikimedia.org/wikipedia/commons/thumb/5/59/RhinopitecusBieti.jpg/320px-RhinopitecusBieti.jpg"
        });

        source.Add(new Monkey
        {
            Name = "Tonkin Snub-nosed Monkey",
            Location = "Vietnam",
            Details = "The Tonkin snub-nosed monkey or Dollman's snub-nosed monkey is a slender-bodied arboreal Old World monkey, endemic to northern Vietnam. It is a black and white monkey with a pink nose and lips and blue patches round the eyes. It is found at altitudes of 200 to 1,200 m (700 to 3,900 ft) on fragmentary patches of forest on craggy limestone areas. First described in 1912, the monkey was rediscovered in 1990 but is exceedingly rare. In 2008, fewer than 250 individuals were thought to exist, and the species was the subject of intense conservation effort. The main threats faced by these monkeys is habitat loss and hunting, and the International Union for Conservation of Nature has rated the species as "critically endangered".",
            ImageUrl = "https://upload.wikimedia.org/wikipedia/commons/thumb/9/9c/Tonkin_snub-nosed_monkeys_%28Rhinopithecus_avunculus%29.jpg/320px-Tonkin_snub-nosed_monkeys_%28Rhinopithecus_avunculus%29.jpg"
        });

        source.Add(new Monkey
        {
            Name = "Thomas's Langur",
            Location = "Indonesia",
            Details = "Thomas's langur is a species of primate in the family Cercopithecidae. It is endemic to North Sumatra, Indonesia. Its natural habitat is subtropical or tropical dry forests. It is threatened by habitat loss. Its native names are reungkah in Acehnese and kedih in Alas.",
            ImageUrl = "https://upload.wikimedia.org/wikipedia/commons/thumb/3/31/Thomas%27s_langur_Presbytis_thomasi.jpg/142px-Thomas%27s_langur_Presbytis_thomasi.jpg"
        });

        source.Add(new Monkey
        {
            Name = "Purple-faced Langur",
            Location = "Sri Lanka",
            Details = "The purple-faced langur, also known as the purple-faced leaf monkey, is a species of Old World monkey that is endemic to Sri Lanka. The animal is a long-tailed arboreal species, identified by a mostly brown appearance, dark face (with paler lower face) and a very shy nature. The species was once highly prevalent, found in suburban Colombo and the "wet zone" villages (areas with high temperatures and high humidity throughout the year, whilst rain deluges occur during the monsoon seasons), but rapid urbanization has led to a significant decrease in the population level of the monkeys.",
            ImageUrl = "https://upload.wikimedia.org/wikipedia/commons/thumb/0/02/Semnopithèque_blanchâtre_mâle.JPG/192px-Semnopithèque_blanchâtre_mâle.JPG"
        });

        source.Add(new Monkey
        {
            Name = "Gelada",
            Location = "Ethiopia",
            Details = "The gelada, sometimes called the bleeding-heart monkey or the gelada baboon, is a species of Old World monkey found only in the Ethiopian Highlands, with large populations in the Semien Mountains. Theropithecus is derived from the Greek root words for "beast-ape." Like its close relatives the baboons, it is largely terrestrial, spending much of its time foraging in grasslands.",
            ImageUrl = "https://upload.wikimedia.org/wikipedia/commons/thumb/1/13/Gelada-Pavian.jpg/320px-Gelada-Pavian.jpg"
        });

        Monkeys = new ObservableCollection<Monkey>(source);
    }

 

    #region INotifyPropertyChanged
    public event PropertyChangedEventHandler PropertyChanged;

    void OnPropertyChanged([CallerMemberName] string propertyName = null)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
    #endregion
}

【讨论】:

  • 感谢您的输入。我已将您的代码集成到 GitHub 项目中:github.com/otium99/MonkeyBusiness 我这边的结果是:当元素设置为不可见时,VerticalStackLayout 内的空间正在坍塌。是的,在这种情况下,整个页面都在滚动。但我想要的行为是,只有 CollectionView 滚动,而其余的则保持原位。
  • 我已经更新了我的答案。您可以查看我回复的更新部分。
  • 我已将新代码集成到 GitHub 项目中,并添加了一个简短的行为视频。它仍然滚动整个页面。
  • 就像我上面提到的,如果你在另一个滚动视图中包含一个滚动视图,这可能会导致用户不需要的行为和复杂性。所以你可以将CollectionView.Header添加到CollectionView。这意味着页眉是“CollectionView”的一部分,它必然会与整个页面一起滚动。
  • 我仍在寻找标题保持固定的解决方案。
【解决方案2】:

经过大量研究,我找到了解决此问题的好方法。

您应该使用 BindableLayout 而不是任何类型的 CollectionView 或 ListView。

BindableLayouts 会根据内容自动调整大小。

  <StackLayout BindableLayout.ItemsSource="{Binding Items}"
                     Orientation="Vertical">
        <BindableLayout.ItemTemplate>
                <DataTemplate x:DataType="{x:Type model:ListItem}">
                    <VerticalStackLayout>
                        <TapGestureRecognizer
                            Command="{Binding Source={RelativeSource
                            AncestorType={x:Type views:MyViewModel}},
                            Path=TapOnSelectedItemCommand}"
                            NumberOfTapsRequired="1" 
                            CommandParameter="{Binding .}"/>
                    </VerticalStackLayout.GestureRecognizers>
                
                    <HorizontalStackLayout>
                        <Label Text="{Binding ListItem.Name}"/>
                        
                        <Button Text="..."
                                Command="{Binding DetailsButtonCommand}"
                                HorizontalOptions="End"
                                />
                    </HorizontalStackLayout>
                    
                
                    <VerticalStackLayout IsVisible="{Binding IsExpanded }">
                        <Label Text="EXPANDED"/>
                        <Button Text="Test"
                                Command="{Binding Source={RelativeSource
                                AncestorType={x:Type views: MyViewModel}},
                                Path=DetailsButtonClickedCommand}"
                                CommandParameter="{Binding .}"/>
                    </VerticalStackLayout>
                
                </VerticalStackLayout>
            </DataTemplate>
        </BindableLayout.ItemTemplate>
    </StackLayout>                        

                   

接下来,我设置了一个 TapGestureRecognizer 来检测项目上的点击,这会折叠/展开它们。他们在后面的代码中调用一个命令,该命令将触发一个 bool,该 bool 被设置为上面提到的 IsVisible 组件。

我跟踪哪些项目已展开/未展开,并相应地切换它。

【讨论】:

    【解决方案3】:

    我试图做同样的事情,虽然 Adam 的想法是正确的,但代码不完整并且花了很长时间才弄清楚。

    此外,在上面的其他示例中,CollectionView 不支持折叠组,但 BindableLayout 支持。

    我创建了一个完整的演示项目并将其放在 github 上:https://github.com/sej69/MauiGroupedList

    这就是它的样子:

    这是需要做的事情的基础。

    (使用 CommunityToolkit)

    基本数据模型,这是将在每个标题中分组的数据。

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    
    namespace MauiGrouping.Models
    {
        public class Animal
        {
            public string name { get; set; }
            public string location { get; set; }
            public string details { get; set; }
        }
    }
    

    分组/列表数据模型,这是分组列表类,在这个例子中标题是“字符串种类”。

    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Linq;
    using System.Runtime.CompilerServices;
    using System.Text;
    using System.Threading.Tasks;
    
    namespace MauiGrouping.Models
    {
    // iNotifyPropertyChanged is includede even though we are using community toolkit as
    // a class can only inherit one parent class
    public class AnimalList : List<Animal>, INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;
    
        public string species { get; private set; }
    
        // variables to control open / close groupings
        private bool _isExpanded = true;
        private bool _notExpanded = false;
    
        public bool IsExpanded
        {
            get => _isExpanded;
            set => SetField(ref _isExpanded, value);
        }
    
        public bool NotExpanded
        {
            get => _notExpanded;
            set => SetField(ref _notExpanded, value);
        }
    
        public List<Animal>? animals { get; private set; }
    
        public AnimalList(string? species, List<Animal>? animals) : base(animals)
        {
            this.species = species;
            this.animals = animals;
        }
    
    
        protected void OnPropertyChanged(string propertyName)
           => PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    
        protected bool SetField<T>(ref T field, T value, [CallerMemberName] string propertyName = "")
        {
            if (EqualityComparer<T>.Default.Equals(field, value)) return false;
            field = value;
            OnPropertyChanged(propertyName);
            return true;
        }
    }
    }
    

    我在这里使用 OnPropertyChanged 的​​原因是因为 C# 中的类只能从单个类继承。为了让它工作,我们需要从父数据模型继承。这是唯一没有使用 CommunityToolkit 的地方。

    风景:

    <?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="MauiGrouping.Pages.AnimalsPage"
             xmlns:viewmodel="clr-namespace:MauiGrouping.ViewModels"
             xmlns:dm="clr-namespace:MauiGrouping.Models"
             Title="Animals">
    
    <ScrollView VerticalScrollBarVisibility="Always" VerticalOptions="FillAndExpand">
        <VerticalStackLayout >
            <StackLayout BindableLayout.ItemsSource="{Binding AllAnimals}" Orientation="Vertical">
                <BindableLayout.ItemTemplate>
                    <DataTemplate x:DataType="dm:AnimalList">
                        <!-- Header (group info) here -->
                        <StackLayout>
                            <Frame BackgroundColor="BlueViolet" MaximumWidthRequest="200" HorizontalOptions="Start">
                                <HorizontalStackLayout>
                                    <!-- the following will arrow down/right if the grouping is expanded or not -->
                                    <ImageButton Source="down_arrow.png" HeightRequest="25" WidthRequest="25" 
                                         Command="{Binding Source={RelativeSource
                                         AncestorType={x:Type viewmodel:AnimalsViewModel}},
                                         Path=ExpandCommand}" CommandParameter="{Binding .}" IsVisible="{Binding IsExpanded}"/>
                                    <ImageButton Source="right_arrow.png" HeightRequest="15" WidthRequest="25" 
                                         Command="{Binding Source={RelativeSource
                                         AncestorType={x:Type viewmodel:AnimalsViewModel}},
                                         Path=ExpandCommand}" CommandParameter="{Binding .}" IsVisible="{Binding NotExpanded}"/>
    
                                    <Label Text= "{Binding species}" Padding="5,0,20,0"/>
    
                                </HorizontalStackLayout>
                            </Frame>
    
                            <!-- list data here -->
                            <StackLayout BindableLayout.ItemsSource="{Binding .}" IsVisible="{Binding IsExpanded}">
                                <BindableLayout.ItemTemplate>
                                    <DataTemplate x:DataType="dm:Animal">
                                        <Frame BackgroundColor="DarkGreen" Margin="20,0,15,0">
                                            <VerticalStackLayout>
                                            <HorizontalStackLayout>
                                                <Label Text="{Binding name}" Padding="0,0,30,0" />
                                                <Label Text="{Binding location}" Padding="0,0,5,0"/>
                                                </HorizontalStackLayout>
                                                <Label Text="{Binding details}" Padding="0,0,10,0" />
                                            </VerticalStackLayout>
                                        </Frame>
                                    </DataTemplate>
                                </BindableLayout.ItemTemplate>
                            </StackLayout>
                        </StackLayout>
                    </DataTemplate>
                </BindableLayout.ItemTemplate>
            </StackLayout>
        </VerticalStackLayout>
    </ScrollView>
    
    </ContentPage>
    

    视图模型:

    using CommunityToolkit.Mvvm.ComponentModel;
    using System;
    using System.Collections.Generic;
    using System.Collections.ObjectModel;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    using MauiGrouping.Models;
    using CommunityToolkit.Mvvm.Input;
    
    namespace MauiGrouping.ViewModels
    {
    public partial class AnimalsViewModel : ObservableObject
    {
        [ObservableProperty]
        public ObservableCollection<AnimalList> allAnimals;
        public AnimalsViewModel() { }
    
        // This is a little convoluted but the data needs to be entered in a constructor
        // not sure why, but it works
        public void LoadData()
        {
            // initialize list
            AllAnimals = new ObservableCollection<AnimalList>();
    
            // first create a list of all animals to be inserted into the observableCollection
            // for example purposes only, you'll be importing data from other means
            List<Animal> bears = new List<Animal>();
            List<Animal> monkeys = new List<Animal>();
    
            monkeys.Add(new Animal
            {
                name = "Mandrill",
                location = "Southern Cameroon, Gabon, Equatorial Guinea, and Congo",
                details = "The mandrill is a primate of the Old World Animal family, closely related to the baboons and even more closely to the drill. It is found in southern Cameroon, Gabon, Equatorial Guinea, and Congo."
            });
    
            monkeys.Add(new Animal
            {
                name = "Proboscis Animal",
                location = "Borneo",
                details = "The proboscis Animal or long-nosed Animal, known as the bekantan in Malay, is a reddish-brown arboreal Old World Animal that is endemic to the south-east Asian island of Borneo."
            });
    
            monkeys.Add(new Animal
            {
                name = "Red-shanked Douc",
                location = "Vietnam, Laos",
                details = "The red-shanked douc is a species of Old World Animal, among the most colourful of all primates. This Animal is sometimes called the "costumed ape" for its extravagant appearance. From its knees to its ankles it sports maroon-red "stockings", and it appears to wear white forearm length gloves. Its attire is finished with black hands and feet. The golden face is framed by a white ruff, which is considerably fluffier in males. The eyelids are a soft powder blue. The tail is white with a triangle of white hair at the base. Males of all ages have a white spot on both sides of the corners of the rump patch, and red and white genitals."
            });
    
            bears.Add(new Animal
            {
                name = "Black",
                location = "North America",
                details = "The black bear is a shy and native bear in North America"
            });
    
            bears.Add(new Animal
            {
                name = "Polar",
                location = "Canada",
                details = "The polar bear is one of the largest bears on the planet."
            });
    
            // now we insert this information into the observable list here
            // again, this is messy, but it's to demo the groupings
            AnimalList allMonkeys = new AnimalList("Monkeys", monkeys);
            AnimalList allBears = new AnimalList("Bears", bears);
    
            // note the capital letter starting the variable here
            AllAnimals.Add(allMonkeys);
            AllAnimals.Add(allBears);
    
        }
    
        [RelayCommand]
        public void Expand(AnimalList arg)
        {
            arg.IsExpanded = !arg.IsExpanded;  // flip / flop buttons
            arg.NotExpanded = !arg.NotExpanded;
        }
    }
    }
    

    同样,有关其工作原理的完整工作演示,请参阅 github 存储库。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2018-12-13
      • 2013-06-06
      • 1970-01-01
      • 1970-01-01
      • 2011-09-12
      • 1970-01-01
      • 2023-01-25
      相关资源
      最近更新 更多