Reputation: 87
I have a big list of objects retrieved through parsing a JSON file. Right now I'm binding said list to a ListView
but the list is unwieldy and I wanted to divide it in separate groups for an ease of use. I tried following several different guides but I'm unable to prepare my data in the correct way. If I manually initialize one of my sorted lists with some items they do show up so the code is indeed functioning.
My grouping model:
public class SortedItem
{
public string Header { get; set; }
public List<Item> Items { get; set; }
public SortedItem(string header)
{
Header = header;
}
}
My object model:
public class Item
{
public string item { get; set; }
//public int icon { get; set; }
private string ico;
public string icon
{
get { return ico; }
set { ico = "Icons/" + value + ".png"; }
}
public int id { get; set; }
public string slot { get; set; }
public string scrip { get; set; }
public Reduce reduce { get; set; }
public int lvl { get; set; }
public string zone { get; set; }
public int time { get; set; }
}
Right now my XAML is as follows:
<?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="Eorzea_Gatherer.Pages.NodesPage"
xmlns:ios="clr-namespace:Xamarin.Forms.PlatformConfiguration.iOSSpecific;assembly=Xamarin.Forms.Core"
ios:Page.UseSafeArea="true"
BackgroundColor="#F4F4F4">
<!--https://xamarinhelp.com/safeareainsets-xamarin-forms-ios/-->
<ListView x:Name="nodesListView"
IsGroupingEnabled="True"
GroupDisplayBinding="{Binding Header}"
HasUnevenRows="True"
BackgroundColor="#F4F4F4"
Margin="30, 30, 30, 0">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<Grid Padding="0, 5">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="60"/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<Image Source="{Binding icon}"
HeightRequest="50"
WidthRequest="50"
Grid.Column="0"/>
<StackLayout Grid.Column="1">
<Label Text="{Binding item}"
TextColor="#171717"
FontSize="13"
FontFamily="SegoeUI"/>
<!--https://forums.xamarin.com/discussion/97996/binding-more-than-one-property-in-listview-->
<Label TextColor="#171717"
FontSize="12"
FontFamily="SegoeUI">
<Label.FormattedText>
<FormattedString>
<Span Text="{Binding zone}"/>
<Span Text=" - "/>
<Span Text="{Binding slot}"/>
</FormattedString>
</Label.FormattedText>
</Label>
<Label TextColor="#171717"
FontSize="12"
FontFamily="SegoeUI">
<Label.FormattedText>
<FormattedString>
<Span Text="{Binding time}"/>
<Span Text=" - "/>
<Span Text="00:00 AM"/>
</FormattedString>
</Label.FormattedText>
</Label>
</StackLayout>
</Grid>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
The function I'm using to retrieve the list and to bind it as a source to the ListView:
public static List<SortedItem> GetSortedItems()
{
List<Item> items = GetItems();
List<SortedItem> sortedItems = new List<SortedItem>()
{
new SortedItem("50")
{
Items = items.Where(x => x.lvl == 50).ToList()
},
new SortedItem("55"),
new SortedItem("60"),
new SortedItem("65"),
new SortedItem("70")
};
return sortedItems;
}
With my code I'm able to see the different groups in my ListView (50, 55, ...) but nothing else pops out. I'm sure my issue is taking my objects list and splitting it in an appropriate way but I'm stumped. What puzzles me is during debugging when hovering on the resulting sortedItems
I get to see my first group does contain the objects it needs to but they still don't show up in the view.
Upvotes: 0
Views: 666
Reputation: 378
I may have missed something, but where are you binding your List<item> Items
at? I think your ListView
is missing something like ItemSource="{Binding Items}"
From there, it looks like your ViewCell
is bound fine and should work as expected.
Upvotes: 1
Reputation: 6641
You should make your grouping model inherit from ObservableCollection
:
public class SortedItem : ObservableCollection<Item>
{
public string Header { get; set; }
public SortedItem(List<Item> list) : base(list)
{
}
}
Then sort it like:
public static List<SortedItem> GetSortedItems()
{
List<Item> items = GetItems();
List<SortedItem> sortedItems = new List<SortedItem>()
{
new SortedItem(items.Where(x => x.lvl == 50).ToList())
{
Header = "50"
},
new SortedItem(items.Where(x => x.lvl == 55).ToList())
{
Header = "55"
},
new SortedItem(items.Where(x => x.lvl == 60).ToList())
{
Header = "60"
},
new SortedItem(items.Where(x => x.lvl == 65).ToList())
{
Header = "65"
},
new SortedItem(items.Where(x => x.lvl == 70).ToList())
{
Header = "70"
}
};
return sortedItems;
}
Moreover, try to implement the INotifyPropertyChanged
interface in your model. Otherwise, the UI won't be notified if you changed the model's property at runtime.
Upvotes: 1
Reputation: 89214
try this, stolen from James Montemagno
public class Grouping<K, T> : ObservableCollection<T>
{
public K Key { get; private set; }
public Grouping(K key, IEnumerable<T> items)
{
Key = key;
foreach (var item in items)
this.Items.Add(item);
}
}
var sorted = from item in Items
orderby item.lvl
group item by item.lvl into itemGroup
select new Grouping<int, Item>(itemGroup.Key, itemGroup);
//create a new collection of groups
ItemsGrouped = new ObservableCollection<Grouping<int, Item>>(sorted);
then in your XAML
GroupDisplayBinding="{Binding Key}"
Upvotes: 2