Xamarin - Grouping List Views - c#

I've got some issues with grouping my List Views.
When I isgroupingenabled = "true" my List only shows the groupDisplayBinding name.
I've read and tried so many things and wasn't able to apply them to my project I need your help now.
I've seen I need to put an Observablecollection but don't know where and how to do it.
My Model
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; }
}
My JSON : (Part of it)
{"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
}
}
]
}
}
ListMatchPage :
public partial class ListMatchs : ContentPage
{
string JsonLeagues = "The Json Below"
public ListMatchs()
{
InitializeComponent();
var Leagues = JsonConvert.DeserializeObject<RootFixtures>(JsonLeagues);
LeaguesList.ItemsSource = Leagues.api.Fixtures;
}
}
I'm new at dev and here I Hope my english wasn't too bad.
edit :
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>

#JackHUA here is what I did :
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>
The image result :
See the pic
But when I change
LeaguesList.ItemsSource = FixturesCollection;
in
LeaguesList.ItemsSource = FixturesCollection.GroupBy(F => F.FixtureLeague);
I get this : See the pic
With error :
[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'...
The List is groupedby but my Binding are not found
I can't find what property to Bind.

The model you added to the ItemsSource should in a right format as the document mentioned, I wrote a example for you and you can check the code:
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;
}
}
And in code behind:
<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>
I also uploaded my sample project here and feel free to ask me any question.
Update:
I think what you really need is OrderBy not GroupBy:
LeaguesList.ItemsSource = FixturesCollection.OrderBy(f => f.FixtureLeague).ToList();
When you use GroupBy, you can set a breakpoint right there to check the LeaguesList.ItemsSource, you will find the structure has been change, the count of LeaguesList.ItemsSource becomes 56.
There is another problem in your xaml, the GroupDisplayBinding should bind to FixtureLeague not name:
<ListView x:Name="LeaguesList" GroupDisplayBinding="{Binding FixtureLeague}"

Related

ListView ItemSource ObservableRangeCollection<> accessing Model ObservableRangeCollection<>

I'm developing an .NET Xamarin App. I want to list all Products as ItemTemplate in the Grouped-ListView and Invoice.Name as Header. Currently I only get the GroupHeaderTemplate shown in my Grouped-ListView.
Model: Invoice.cs
public class Invoice : ObservableRangeCollection<Invoice>
{
public string Name { get; set; }
public Company Company { get; set; }
public ObservableRangeCollection<Product> Products { get; set; }
}
Model: Products.cs
public class Product : ObservableRangeCollection<Product>
{
public string Name { get; set; }
public DateTime ExpireDate { get; set; }
}
ViewModel: MainViewVM (creating fake data)
public ObservableRangeCollection<Invoice> Invoices { get; set; }
public MainViewVM()
{
Invoices.Add(new Invoice { Name = "Test1", Company = new Company { Image = image }, Products = new ObservableRangeCollection<Product>() { new Product { Name = "ProductTest1", CreatedDate = DateTime.Now }, new Product { Name = "ProductTest2", CreatedDate = DateTime.Now } } });
Invoices.Add(new Invoice { Name = "Test2", Company = new Company { Image = image }, Products = new ObservableRangeCollection<Product>() { new Product { Name = "ProductTest3", CreatedDate = DateTime.Now }, new Product { Name = "ProductTest4", CreatedDate = DateTime.Now } } });
}
View: MainViewVM (ListView)
<ListView
IsGroupingEnabled="True"
ItemsSource="{Binding Invoices}">
<ListView.GroupHeaderTemplate>
<DataTemplate x:DataType="models:Invoice">
<ViewCell>
<StackLayout Orientation="Horizontal" VerticalOptions="Center" HorizontalOptions="Center">
<Image Source="{Binding Company.Image}" WidthRequest="66" VerticalOptions="Center"/>
<Label Text="{Binding Name}" VerticalOptions="Center"/>
</StackLayout>
</ViewCell>
</DataTemplate>
</ListView.GroupHeaderTemplate>
<ListView.ItemTemplate>
<DataTemplate x:DataType="models:Product">
<ViewCell>
<StackLayout VerticalOptions="Center">
<Label Text="{Binding Name}" VerticalOptions="Center"/>
</StackLayout>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
I added a constructor with : base. That fixed it for me.
https://learn.microsoft.com/de-de/xamarin/xamarin-forms/user-interface/collectionview/grouping
public Invoice(string name, Company company, ObservableRangeCollection<Product> products) : base(products)
{
Name = name;
Company = company;
Products = products;
}

How to change MapType of Map in VM?

I have a map which want to add from VM. I tried to add command when you click on button MapType will be changed.but it does not working.I know how to make it in codebehind.but I need VM
ContentView
AbsoluteLayout.LayoutBounds="0, 0, 1, 1"
AbsoluteLayout.LayoutFlags="All"
Content="{Binding Map}" />
VM
public Map Map { get; set; }
public Command StandartMapCommand { get; set; }
public Command SatelliteMapCommand { get; set; }
public Command HybridMapCommand { get; set; }
public MasterPageVM()
{
Map = new Map();
StandartMapCommand = new Command(StandardSelected);
SatelliteMapCommand = new Command(SatelliteSelected);
HybridMapCommand = new Command(HybridSelected);
}
public void StandardSelected()
{
Map.MapType = Xamarin.Forms.Maps.MapType.Street;
}
public void HybridSelected()
{
Map.MapType = Xamarin.Forms.Maps.MapType.Hybrid;
}
public void SatelliteSelected()
{
Map.MapType = Xamarin.Forms.Maps.MapType.Satellite;
}
When I click on button map does not change MapType.pls help
I have a map which want to add from VM. I tried to add command when you click on button MapType will be changed.but it does not working.I know how to make it in codebehind.but I need VM
If you want to change Map.Maptype in viewmodel, you can take a look the following code.
<ContentPage.Content>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<ContentView Grid.ColumnSpan="3" Content="{Binding Map}" />
<Button
x:Name="btn1"
Grid.Row="1"
Command="{Binding StandartMapCommand}"
Text="Street" />
<Button
x:Name="btn2"
Grid.Row="1"
Grid.Column="1"
Command="{Binding SatelliteMapCommand}"
Text="Satellite" />
<Button
x:Name="btn3"
Grid.Row="1"
Grid.Column="2"
Command="{Binding HybridMapCommand}"
Text="Hybrid" />
</Grid>
</ContentPage.Content>
public partial class Page1 : ContentPage
{
public Page1 ()
{
InitializeComponent ();
this.BindingContext = new MapViewModel();
}
}
public class MapViewModel
{
private Map _map;
public Map Map
{
get { return _map; }
set
{
_map = value;
}
}
public Command StandartMapCommand { get; set; }
public Command SatelliteMapCommand { get; set; }
public Command HybridMapCommand { get; set; }
public MapViewModel()
{
Map = new Map();
Position position = new Position(36.9628066, -122.0194722);
MapSpan mapSpan = new MapSpan(position, 0.01, 0.01);
Map.MoveToRegion(mapSpan);
Map.Pins.Add(new Pin
{
Label = "Xamarin",
Position = position
});
StandartMapCommand = new Command(streetcommand);
SatelliteMapCommand = new Command(Satellitecommand);
HybridMapCommand = new Command(Hybridcommand);
}
private void streetcommand()
{
Map.MapType = MapType.Street;
}
private void Satellitecommand()
{
Map.MapType = MapType.Satellite;
}
private void Hybridcommand()
{
Map.MapType = MapType.Hybrid;
}
}

Xamarin.Forms reload a collectionview

I am using Xamarin Forms and I have created a collection view, I am getting the data from an api after getting the device location, my question is how can I reload the collectionview? Here is my code:
public partial class HomePage : ContentPage
{
APIClass aPIClass = new APIClass();
public HomePage()
{
InitializeComponent();
getLocation();
}
public async void getLocation()
{
try
{
var location = await Geolocation.GetLastKnownLocationAsync();
if (location != null)
{
HomeClass places = aPIClass.getUserPlace(location.Latitude.ToString(), location.Longitude.ToString());
HomeCollection.ItemsSource = places.results;
Console.WriteLine($"Latitude: {location.Latitude}, Longitude: {location.Longitude}, Altitude: {location.Altitude}");
}
}
catch(Exception e)
{
Console.WriteLine(e.Message.ToString());
}
}
}
And my view:
<CollectionView x:Name="HomeCollection">
<CollectionView.ItemsLayout>
<GridItemsLayout Orientation="Vertical" />
</CollectionView.ItemsLayout>
<CollectionView.ItemTemplate>
<DataTemplate>
<Grid Padding="10">
<Grid.RowDefinitions>
<RowDefinition Height="150" />
<RowDefinition Height="35" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<BoxView Color="White" Grid.Column="1" Grid.RowSpan="2"/>
<ContentView Padding="10" Grid.Row="0" Grid.Column="1">
<Image Grid.Row="0" Grid.Column="1" Source="{Binding photos[0].name}" Aspect="AspectFill" />
</ContentView>
<ContentView Padding="10" Grid.Row="1" Grid.Column="1">
<Label Grid.Row="1"
Grid.Column="1"
Text="{Binding name}" />
</ContentView>
</Grid>
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
Classes involved:
public class HomeClass
{
public List<PlacesClass> results { get; set; }
}
public class PlacesClass
{
public string name { get; set; }
public List<PlacesImageClass> photos { get; set; }
}
public class PlacesImageClass
{
public int height { get; set; }
public List<string> html_attributions { get; set; }
public string photo_reference { get; set; }
public int width { get; set; }
public string name { get; set; }
}

C# Xamarin forms Nested Listiews in TabbedPage with ObservableCollection

I am trying to create different tabs with different nested ListViews binding to ObservableCollection.
This is getting a bit over my head. It should be very simple to solve.
This is how my TabbedPage xaml looks like
<TabbedPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:d="http://xamarin.com/schemas/2014/forms/design"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
x:Class="scorePredict.Views.TabbedItemsPage" ItemsSource="{Binding Things}">
<!--Pages can be added as references or inline-->
<TabbedPage.ItemTemplate>
<DataTemplate>
<ContentPage Title="{Binding description}">
<StackLayout>
<ListView ItemsSource="{Binding DetailedViewModel.sortedItems}">
<ListView.HeaderTemplate >
<DataTemplate>
<Grid BackgroundColor="Black">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="50" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Label Text="Time" Grid.Column="0" Margin="5,0,0,0" TextColor="Gold" HorizontalOptions="StartAndExpand" HeightRequest="20" WidthRequest="50"/>
<Label Text="Host" Grid.Column="1" TextColor="Gold" HorizontalOptions="CenterAndExpand" Margin="0,0,170,0"/>
<Label Text="Guest" Grid.Column="1" TextColor="Gold" HorizontalOptions="CenterAndExpand" Margin="110,0,0,0"/>
<Label Text="TIP" HorizontalOptions="EndAndExpand" TextColor="Gold" Grid.Column="1"/>
</Grid>
</DataTemplate>
</ListView.HeaderTemplate>
<ListView.Header >
<StackLayout Padding="10,5,0,5" BackgroundColor="Green" Orientation="Horizontal">
<Label Text="{Binding Name}" />
<Label Text="{Binding Description}" FontSize="Small"/>
</StackLayout>
</ListView.Header>
<ListView.GroupHeaderTemplate >
<DataTemplate>
<ViewCell Height="30">
<StackLayout Orientation="Horizontal"
BackgroundColor="Goldenrod"
VerticalOptions="FillAndExpand">
<Image Source="{Binding imagePath}" VerticalOptions="Center" HorizontalOptions="Start" HeightRequest="20" WidthRequest="20"/>
<Label Text="{Binding Intro} " VerticalOptions="Center"/>
<Label Text="{Binding Summary}" VerticalOptions="Center"/>
<Label Text="TIP" VerticalOptions="Center" HorizontalOptions="EndAndExpand"/>
</StackLayout>
</ViewCell>
</DataTemplate>
</ListView.GroupHeaderTemplate>
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<ViewCell.View>
<Grid Padding="5">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="50" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Label Text="{Binding Time}" Grid.Column="0"></Label>
<Label Text="{Binding TeamOne}" Grid.Column="1" HorizontalTextAlignment="End" HorizontalOptions="CenterAndExpand" Margin="0,0,170,0"></Label>
<Label Text="{Binding ScoreTeamOne}" Grid.Column="1" TextColor="White" HorizontalOptions="CenterAndExpand" HorizontalTextAlignment="Center" Margin="0,0,50,0" WidthRequest="20" BackgroundColor="Gray"></Label>
<Label Text="{Binding ScoreTeamTwo}" Grid.Column="1" TextColor="White" HorizontalOptions="CenterAndExpand" HorizontalTextAlignment="Center" Margin="0,0,5,0" WidthRequest="20" BackgroundColor="Gray"></Label>
<Label Text="{Binding TeamTwo}" Grid.Column="1" HorizontalTextAlignment="Start" HorizontalOptions="CenterAndExpand" Margin="110,0,0,0"></Label>
<Label Text="{Binding Tip}" Grid.Column="1" HorizontalOptions="EndAndExpand" WidthRequest="20" HorizontalTextAlignment="Center" TextColor="White" BackgroundColor="{Binding TipBGColor}"></Label>
</Grid>
</ViewCell.View>
</ViewCell>
<!--<TextCell Text="{Binding Name}" Detail="{Binding Description}"></TextCell>-->
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</StackLayout>
</ContentPage>
</DataTemplate>
</TabbedPage.ItemTemplate>
</TabbedPage>
This is the background code
public TabbedItemsPage()
{
InitializeComponent();
BindingContext = new CurrentStatusDeviceViewModel();
}
public class CurrentStatusDeviceViewModel
{
public ObservableCollection<TabViewModel> Things { set; get; }
public CurrentStatusDeviceViewModel()
{
// Here I create three demo pages
Things = new ObservableCollection<TabViewModel>();
for (int i = 0; i < 7; i++)
{
Things.Add(new TabViewModel(i.ToString()) { description = "description" + i });
}
}
}
public class TabViewModel
{
public string description { set; get; }
public string TabID { set; get; }
public CurrentStatusDeviceDetailedViewModel DetailedViewModel { set; get; }
public TabViewModel(string tabID)
{
TabID = tabID;
// Pass Tab ID to the second view model
DetailedViewModel = new CurrentStatusDeviceDetailedViewModel(tabID);
}
}
public class CurrentStatusDeviceDetailedViewModel
{
public string CurrentID { set; get; }
public ObservableCollection<Titles> sortedItems { get; set; }
public ObservableCollection<Item> items { get; set; }
public CurrentStatusDeviceDetailedViewModel(string tabId)
{
CurrentID = tabId;
// I simulate the lists here
sortedItems = new ObservableCollection<Titles>();
items = new ObservableCollection<Item>();
for (int i = 0; i < 5; i++)
{
for (int x = 0; x < 10; x++)
{
items.Add(new Item { Time = CurrentID + i, TeamOne = "Barcelona", ScoreTeamOne = "2", TeamTwo = "Real Madrid", ScoreTeamTwo = "1" });
}
sortedItems.Add(new Titles(items.ToList()) { Intro = "This is a big header", Summary = "This is the end" });
items.Clear();
}
}
}
And these are my classes for the lists
public class Titles : ObservableCollection<Item>
{
//public List<Matches> Monkeys { get; set; }
public string Intro { get; set; }
public string Summary { get; set; }
public Uri imagePath { get; set; }
public Titles(List<Item> list) : base(list)
{
}
}
public class Item
{
public string Id { get; set; }
public string Text { get; set; }
public string Description { get; set; }
public string Href { get; set; }
public string Time { get; set; }
public string TeamOne { get; set; }
public string ScoreTeamOne { get; set; }
public string ScoreTeamTwo { get; set; }
public string TeamTwo { get; set; }
public string Tip { get; set; }
public Color TipBGColor { get; set; }
}
My problem here is that the five headers are created but items are not created within them and the titles of the headers are not binded.
It is just empty.
Any ideas?
What you need to do is set the IsGroupingEnabled of ListView to true :
<ListView ItemsSource="{Binding DetailedViewModel.sortedItems}" IsGroupingEnabled="True">
The document is here: customizing-list-appearance#grouping
You need to enable grouping in your Listview
<ListView ItemsSource="{Binding DetailedViewModel.sortedItems}" IsGroupingEnabled="True">

Max rows listview xamarin

I have a list view that displays a ladder of points on a sports team and am trying to only show the top 5 players. Is there anyway that this can be in XAML?
Thanks,
Ryan
EDIT: Here is my code
XAML:
<?xml version="1.0" encoding="UTF-8"?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" x:Class="MIApp.PlayerPage">
<ContentPage.Content>
<StackLayout Margin="20,0,0,0" Orientation="Vertical" HorizontalOptions="CenterAndExpand" VerticalOptions="CenterAndExpand">
<Label Text="Player Info" HorizontalOptions="CenterAndExpand" VerticalOptions="CenterAndExpand"/>
<Grid MinimumHeightRequest="200" RowSpacing="10" Padding="0">
<Grid.RowDefinitions>
<RowDefinition Height="50"/>
<RowDefinition/>
<RowDefinition Height="50"/>
<RowDefinition/>
</Grid.RowDefinitions>
<Label Text="Goal Leaders" Grid.Row="0" Margin="0"/>
<ListView x:Name="GoalListView" Grid.Row="1">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<StackLayout Orientation="Vertical" Margin="0,0,0,0" Spacing="0" VerticalOptions="Center">
<Label Text="{Binding StrFullName}" HorizontalOptions="Start" VerticalTextAlignment="Center"/>
<Label Text="{Binding IntGoals}" HorizontalOptions="End" VerticalTextAlignment="Center"/>
</StackLayout>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
<Label Text="Point Leaders" Grid.Row="2" Margin="0"/>
<ListView x:Name="PointListView" HasUnevenRows="true" Grid.Row="3" Margin="0,0,0,0">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<StackLayout Orientation="Vertical" Margin="0,0,0,0" Spacing="0" VerticalOptions="Center">
<Label Text="{Binding StrFullName}" HorizontalOptions="Start" VerticalTextAlignment="Center"/>
<Label Text="{Binding IntPoints}" HorizontalOptions="End" VerticalTextAlignment="Center"/>
</StackLayout>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</Grid>
</StackLayout>
</ContentPage.Content>
</ContentPage>
Code Behind:
public partial class PlayerPage : ContentPage
{
public PlayerPage()
{
InitializeComponent();
}
protected async override void OnAppearing()
{
base.OnAppearing();
HttpClient client = new HttpClient();
string urlGoals = "https://melbourneicewebapi.azurewebsites.net/api/Player_Info/GetPlayer_Info?playerInfo=goals";
string urlPoints = "https://melbourneicewebapi.azurewebsites.net/api/Player_Info/GetPlayer_Info?playerInfo=points";
var responseGoals = await client.GetAsync(urlGoals);
var responsePoints = await client.GetAsync(urlPoints);
if (responsePoints.IsSuccessStatusCode)
{
string resGoals = "";
using (HttpContent contentGoals = responseGoals.Content)
{
Task<string> resultGoals = contentGoals.ReadAsStringAsync();
resGoals = resultGoals.Result;
var GoalsList = Players.PlayersItems.FromJson(resGoals);
GoalListView.ItemsSource = GoalsList;
}
string resPoints = "";
using (HttpContent contentPoints = responsePoints.Content)
{
Task<string> resultPoints = contentPoints.ReadAsStringAsync();
resPoints = resultPoints.Result;
var PointsList = Players.PlayersItems.FromJson(resPoints);
PointListView.ItemsSource = PointsList;
}
}
else
{
await DisplayAlert("Connection Error", "Please Connect to the internet and try again", "Ok");
}
}
}
Players Class where objects are created from JSON string and added into a list:
public class Players
{
public partial class PlayersItems
{
[JsonProperty("$id")]
public long Id { get; set; }
[JsonProperty("intPlayerID")]
public int IntPlayerId { get; set; }
[JsonProperty("strFirstName")]
public string StrFirstName { get; set; }
[JsonProperty("strSurname")]
public string StrSurname { get; set; }
[JsonProperty("intGamesPlayed")]
public int IntGamesPlayed { get; set; }
[JsonProperty("strPosition")]
public string StrPosition { get; set; }
[JsonProperty("intPlayerNumber")]
public int IntPlayerNumber { get; set; }
[JsonProperty("intGoals")]
public int IntGoals { get; set; }
[JsonProperty("intAssists")]
public int IntAssists { get; set; }
[JsonProperty("intPoints")]
public int IntPoints { get; set; }
public string StrFullName {
get
{
return StrFirstName.Trim() + " " + StrSurname.Trim();
}
}
}
public partial class PlayersItems
{
public static List<PlayersItems> FromJson(string json)
{
return JsonConvert.DeserializeObject<List<PlayersItems>>(json);
}
}
}
So what I am essentially doing is accessing an API that gives me two JSON Strings of all the data entries in the Players Table,One that is sorted by highest points, the other by highest goals, it is then converted into a list of objects from the Players Class, and then set to the appropriate List View.
use LINQ to select the top X scores before assigning them to ItemsSource. I'm not aware of any way to filter the data directly in XAML
var PointsList = Players.PlayersItems.FromJson(resPoints);
var topPoints = PointsList.OrderByDescending(x => x.PointsInt).Take(5).ToList();
PointListView.ItemsSource = topPoints;

Categories