Xamarin - 分组列表视图

Posted

技术标签:

【中文标题】Xamarin - 分组列表视图【英文标题】:Xamarin - Grouping List Views 【发布时间】:2020-07-03 19:31:09 【问题描述】:

我在对列表视图进行分组时遇到了一些问题。 当我isgroupingenabled = "true" 我的列表只显示groupDisplayBinding 名称。

我已经阅读并尝试了很多东西,但无法将它们应用到我的项目中,我现在需要你的帮助。

我看到我需要输入Observablecollection,但不知道在哪里以及如何操作。

我的模特

        public class League
    
        public string name  get; set; 
        public string country  get; set; 
        public string logo  get; set; 
        public string flag  get; set; 
    

    public class HomeTeam
    
        public int team_id  get; set; 
        public string team_name  get; set; 
        public string logo  get; set; 
    

    public class AwayTeam
    
        public int team_id  get; set; 
        public string team_name  get; set; 
        public string logo  get; set; 
    

    public class Score
    
        public string halftime  get; set; 
        public string fulltime  get; set; 
        public string extratime  get; set; 
        public string penalty  get; set; 
    

    public class Fixture
    
        public int fixture_id  get; set; 
        public int league_id  get; set; 
        public League league  get; set; 
        public DateTime event_date  get; set; 
        public int event_timestamp  get; set; 
        public int? firstHalfStart  get; set; 
        public int? secondHalfStart  get; set; 
        public string round  get; set; 
        public string status  get; set; 
        public string statusShort  get; set; 
        public int elapsed  get; set; 
        public string venue  get; set; 
        public string referee  get; set; 
        public HomeTeam homeTeam  get; set; 
        public AwayTeam awayTeam  get; set; 
        public int? goalsHomeTeam  get; set; 
        public int? goalsAwayTeam  get; set; 
        public Score score  get; set; 
    

    public class Api
    
        public int results  get; set; 
        public List<Fixture> Fixtures  get; set; 
    

    public class RootFixtures
    
        public Api api  get; set; 
    

我的 JSON :(部分)

"api": 
"results": 162,
"fixtures": [
  
    "fixture_id": 234670,
    "league_id": 900,
    "league": 
      "name": "Division 1",
      "country": "Saudi-Arabia",
      "logo": null,
      "flag": "https://media.api-sports.io/flags/sa.svg"
    ,
    "event_date": "2020-03-10T00:00:00+00:00",
    "event_timestamp": 1583798400,
    "firstHalfStart": null,
    "secondHalfStart": null,
    "round": "Regular Season - 28",
    "status": "Match Postponed",
    "statusShort": "PST",
    "elapsed": 0,
    "venue": "Prince Saud bin Jalawi Stadium (al-Khobar (Khobar))",
    "referee": null,
    "homeTeam": 
      "team_id": 2933,
      "team_name": "Al-Qadisiyah FC",
      "logo": "https://media.api-sports.io/teams/2933.png"
    ,
    "awayTeam": 
      "team_id": 2928,
      "team_name": "Al Khaleej Saihat",
      "logo": "https://media.api-sports.io/teams/2928.png"
    ,
    "goalsHomeTeam": null,
    "goalsAwayTeam": null,
    "score": 
      "halftime": null,
      "fulltime": null,
      "extratime": null,
      "penalty": null
    
  
]

列表匹配页面:

    public partial class ListMatchs : ContentPage

    string JsonLeagues = "The Json Below"
    public ListMatchs()
    
        InitializeComponent();

        var Leagues = JsonConvert.DeserializeObject<RootFixtures>(JsonLeagues);

        LeaguesList.ItemsSource = Leagues.api.Fixtures;

    

我是 dev 的新手,在这里我希望我的英语还不错。 编辑: MyXAML:

 <ContentPage.Content>
    <StackLayout>
        <Label Text="Futurs matchs" HorizontalTextAlignment="Center" />
        <ListView x:Name="LeaguesList" GroupDisplayBinding="Binding Path=League.name"
                  GroupShortNameBinding="Binding Path=League.name"
                  IsGroupingEnabled="True" HasUnevenRows="True">
            <ListView.ItemTemplate>
                <DataTemplate>
                    <ViewCell Height="30">
                        <Grid>
                            <Grid.RowDefinitions>
                                <RowDefinition Height="*"/>
                            </Grid.RowDefinitions>
                            <Grid.ColumnDefinitions>
                                <ColumnDefinition Width="20"/>
                                <ColumnDefinition Width="*" />
                                <ColumnDefinition Width="*"/>
                                <ColumnDefinition Width="20" />
                            </Grid.ColumnDefinitions>
                            <Image Grid.Column="0" Aspect="AspectFit" Source="Binding Path=homeTeam.logo" />
                            <Label Grid.Column="1" VerticalOptions="CenterAndExpand" HorizontalTextAlignment="Center" TextColor="Black" FontSize="15" FontAttributes="Bold" Text="Binding Path=homeTeam.team_name" HorizontalOptions="CenterAndExpand"/>
                            <Label Grid.Column="2" VerticalOptions="CenterAndExpand" HorizontalTextAlignment="Center" TextColor="Black" FontSize="15" FontAttributes="Bold" Text="Binding Path=awayTeam.team_name" HorizontalOptions="CenterAndExpand"/>
                            <Image Grid.Column="3" Aspect="AspectFit" Source="Binding Path=awayTeam.logo" />
                        </Grid>
                    </ViewCell>
                </DataTemplate>
            </ListView.ItemTemplate>
        </ListView>
    </StackLayout>
</ContentPage.Content>

【问题讨论】:

LeaguesList 是在哪里定义的? 把 xaml 也发给你,然后我会告诉你如何正确分组数据。 糟糕,我忘记了 LeaguesList 是我在 XAML 中定义的 ListviewName。我用它编辑了我的问题 【参考方案1】:

@JackHUA 这就是我所做的:

XAML.CS :



    ObservableCollection<groupedfix> FixturesCollection = new ObservableCollection<groupedfix>();
public ListMatchs()
        

            InitializeComponent();

            var Leagues = JsonConvert.DeserializeObject<RootFixtures>(JsonLeagues);
            foreach (var match in Leagues.api.Fixtures)

            
                int fixtureid = match.fixture_id;
                DateTime fixturedate = match.event_date;

                int FixtureLeagueid = match.league_id;
                string FixtureLeague = match.league.name;
                string FixtureLeaguelogo = match.league.logo;

                string Hometeamname = match.homeTeam.team_name;
                string Hometeamlogo = match.homeTeam.logo;
                string Awayteamname = match.awayTeam.team_name;
                string Awayteamlogo = match.awayTeam.logo;

                HomeTeam HOMETEAM = new HomeTeam()  team_name = Hometeamname, logo = Hometeamlogo ;
                AwayTeam AWAYTEAM = new AwayTeam()  team_name = Awayteamname, logo = Awayteamlogo ;
                League LEAGUE = new League()  logo = FixtureLeaguelogo, name = FixtureLeague ;

                Fixture MATCH = new Fixture()  fixture_id = fixtureid, event_date = fixturedate, league_id = FixtureLeagueid, league = LEAGUE, homeTeam = HOMETEAM, awayTeam = AWAYTEAM ;

                groupedfix GROUPEDFIX = new groupedfix(FixtureLeague)  MATCH ;

                FixturesCollection.Add(GROUPEDFIX);

            

            LeaguesList.ItemsSource = FixturesCollection;

        


        public class groupedfix : List<Fixture>
        
            public string FixtureLeague  get; set; 

            public groupedfix(string Name )
            
                FixtureLeague = Name;

            

        

XAML:

    <ContentPage.Content>
    <StackLayout>
        <Label Text="Futurs matchs" HorizontalTextAlignment="Center" />
        <ListView x:Name="LeaguesList" GroupDisplayBinding="Binding FixtureLeague"
                  IsGroupingEnabled="True" HasUnevenRows="True" ItemTapped="Newgameclick">
            <ListView.ItemTemplate>
                <DataTemplate> 
                    <ViewCell Height="30">
                        <Grid>
                            <Grid.RowDefinitions>
                                <RowDefinition Height="*"/>
                            </Grid.RowDefinitions>
                            <Grid.ColumnDefinitions>
                                <ColumnDefinition Width="20"/>
                                <ColumnDefinition Width="*" />
                                <ColumnDefinition Width="*"/>
                                <ColumnDefinition Width="20" />
                            </Grid.ColumnDefinitions>
                            <Image Grid.Column="0" Aspect="AspectFit" Source="Binding Path=homeTeam.logo"/>
                            <Label Grid.Column="1" VerticalOptions="CenterAndExpand" HorizontalTextAlignment="Center" TextColor="Black" FontSize="15" FontAttributes="Bold" Text="Binding Path=homeTeam.team_name" HorizontalOptions="CenterAndExpand"/>
                            <Label Grid.Column="2" VerticalOptions="CenterAndExpand" HorizontalTextAlignment="Center" TextColor="Black" FontSize="15" FontAttributes="Bold" Text="Binding Path=awayTeam.team_name" HorizontalOptions="CenterAndExpand"/>
                            <Image Grid.Column="3" Aspect="AspectFit" Source="Binding Path=awayTeam.logo" />
                        </Grid>
                    </ViewCell>
                </DataTemplate>
            </ListView.ItemTemplate>
        </ListView>
    </StackLayout>
</ContentPage.Content>

图像结果: See the pic

但是当我改变时

LeaguesList.ItemsSource = FixturesCollection;

LeaguesList.ItemsSource = FixturesCollection.GroupBy(F => F.FixtureLeague);

我明白了:See the pic

有错误:

[0:] Binding:'FixtureLeague' property not found on 'System.Linq.Grouping`2[System.String,BeastTIPS.Pages.ListMatchs+groupedfix]'...
        [0:] Binding: 'homeTeam' property not found on 'BeastTIPS.Pages.ListMatchs+groupedfix'...
    [0:] Binding: 'awayTeam' property not found on 'BeastTIPS.Pages.ListMatchs+groupedfix'...

列表已分组,但找不到我的绑定 我找不到要绑定的属性。

【讨论】:

【参考方案2】:

您添加到 ItemsSource 的模型应采用正确的格式,如 document mentioned,我为您编写了一个示例,您可以查看代码:

public partial class MainPage : ContentPage

    ObservableCollection<myModel> FixtureCollection = new ObservableCollection<myModel>();
    public MainPage()
    
        InitializeComponent();

        League LeagueOne = new League()  name = "one" ;
        League LeagueTwo = new League()  name = "two" ;
        League LeagueThree = new League()  name = "three" ;

        HomeTeam HomeTeamOne = new HomeTeam()  team_name = "HomeTeamOne" ;
        HomeTeam HomeTeamTwo = new HomeTeam()  team_name = "HomeTeamTwo" ;
        HomeTeam HomeTeamThree = new HomeTeam()  team_name = "HomeTeamThree" ;

        AwayTeam AwayTeamOne = new AwayTeam()  team_name = "AwayTeamOne" ;
        AwayTeam AwayTeamTwo = new AwayTeam()  team_name = "AwayTeamTwo" ;
        AwayTeam AwayTeamThree = new AwayTeam()  team_name = "AwayTeamThree" ;


        Fixture FixtureOne = new Fixture()  league = LeagueOne, homeTeam = HomeTeamOne, awayTeam = AwayTeamOne;
        Fixture FixtureTwo = new Fixture()  league = LeagueTwo, homeTeam = HomeTeamTwo, awayTeam = AwayTeamTwo ;
        Fixture FixtureThree = new Fixture()  league = LeagueThree, homeTeam = HomeTeamThree, awayTeam = AwayTeamThree ;


        myModel myModelOne = new myModel(FixtureOne.league.name)  FixtureOne ;
        myModel myModelTwo = new myModel(FixtureTwo.league.name)  FixtureTwo ;
        myModel myModelThree = new myModel(FixtureThree.league.name) FixtureThree ;

        FixtureCollection.Add(myModelOne);
        FixtureCollection.Add(myModelTwo);
        FixtureCollection.Add(myModelThree);

        LeaguesList.ItemsSource = FixtureCollection;

        BindingContext = this;
    


public class myModel : List<Fixture>

    public string name  get; set; 
    public myModel( string Name) 
        name = Name;
    

在后面的代码中:

<StackLayout>
    <Label Text="Futurs matchs" HorizontalTextAlignment="Center" />
    <ListView x:Name="LeaguesList" 
              GroupDisplayBinding="Binding name"
              GroupShortNameBinding="Binding name"
              IsGroupingEnabled="True" HasUnevenRows="True">
        <ListView.ItemTemplate>
            <DataTemplate>
                <ViewCell Height="30">
                    <Grid>
                        <Grid.RowDefinitions>
                            <RowDefinition Height="*"/>
                        </Grid.RowDefinitions>
                        <Grid.ColumnDefinitions>
                            <ColumnDefinition Width="20"/>
                            <ColumnDefinition Width="*" />
                            <ColumnDefinition Width="*"/>
                            <ColumnDefinition Width="20" />
                        </Grid.ColumnDefinitions>
                        <Image Grid.Column="0" Aspect="AspectFit" Source="Binding Path=homeTeam.logo" />
                        <Label Grid.Column="1" VerticalOptions="CenterAndExpand" HorizontalTextAlignment="Center" TextColor="Black" FontSize="15" FontAttributes="Bold" Text="Binding Path=homeTeam.team_name" HorizontalOptions="CenterAndExpand"/>
                        <Label Grid.Column="2" VerticalOptions="CenterAndExpand" HorizontalTextAlignment="Center" TextColor="Black" FontSize="15" FontAttributes="Bold" Text="Binding Path=awayTeam.team_name" HorizontalOptions="CenterAndExpand"/>
                        <Image Grid.Column="3" Aspect="AspectFit" Source="Binding Path=awayTeam.logo" />
                    </Grid>
                </ViewCell>
            </DataTemplate>
        </ListView.ItemTemplate>
    </ListView>
</StackLayout>

我还上传了我的示例项目here,欢迎随时问我。

更新:

我认为你真正需要的是OrderBy 而不是GroupBy

LeaguesList.ItemsSource = FixturesCollection.OrderBy(f => f.FixtureLeague).ToList();

当你使用GroupBy时,可以在此处设置断点检查LeaguesList.ItemsSource,你会发现结构发生了变化,LeaguesList.ItemsSource的计数变为56。

您的xaml 中还有另一个问题,GroupDisplayBinding 应该绑定到 FixtureLeague 而不是名称:

<ListView x:Name="LeaguesList" GroupDisplayBinding="Binding FixtureLeague"

【讨论】:

首先感谢您的回答。事实是,在 Json 中,我有数千个灯具,无法一一添加,因为它们每天都会通过调用 web api 进行更改。 你可以用for语句来添加,我做的只是一个例子。 我现在有我的游戏和他们自己的联赛,但他们没有按联赛分组我认为集合中的 groupby 应该很好,不是吗?现在谢谢@JackHua 集合中的 groupby 是什么意思?给我看代码,然后我可以更好地帮助你。 我发布了一个答案来显示我的实际设置。当它结束时,我会用正确的答案编辑它而不会忘记提及你

以上是关于Xamarin - 分组列表视图的主要内容,如果未能解决你的问题,请参考以下文章

Xamarin:用于 Android 和 Windows UWP 的 Xamarin 表单中的分组列表的垂直字母索引(跳转列表)

使用绑定时滚动 Xamarin Forms 列表视图

Xamarin根据视单元宽度调整Listview项目高度

Xamarin Listview 分组

Xamarin图表开发基础教程OxyPlot框架

如何从 postgresql 视图表中获取要显示的对象列表