How can I display ListView Items in a Grid - c#

I would like to recreate something similar to this gallery in Xamarin Forms. I want a ListView with grouping and it's items displayed in a grid.
I know how to group items in a ListView, but I don't know how to display the items in a grid. The grid layout looks similar to a Flex Layout but as far as I can see a Flex Layout doesn't have a way to group items. How can I create this in Xamarin?

You should use the new CollectionView for this:
Eg code:
<CollectionView
x:Name="collectionView"
Margin="5"
ItemSizingStrategy="MeasureAllItems"
ItemsSource="{Binding Results}"
SelectionMode="None">
<CollectionView.ItemTemplate>
<DataTemplate>
<Image
HorizontalOptions="CenterAndExpand"
Source="{Binding ImageSource}"
VerticalOptions="CenterAndExpand" />
</DataTemplate>
</CollectionView.ItemTemplate>
<CollectionView.ItemsLayout>
<GridItemsLayout
HorizontalItemSpacing="10"
Orientation="Vertical"
Span="2"
VerticalItemSpacing="10" />
</CollectionView.ItemsLayout>
<CollectionView.EmptyView>
<StackLayout>
<Label
FontSize="Title"
HorizontalOptions="CenterAndExpand"
Text="{locale:Translate Global_No_Data_Found}"
VerticalOptions="CenterAndExpand" />
</StackLayout>
</CollectionView.EmptyView>
</CollectionView>
Here ItemsLayout is what defines how your Items will look options are Grid and Linear.
To add the date part as per the Image use Group header templates just like ListView.
Note that CollectionViewDataTemplates take Views and not ViewCells.
Using ViewCell will throw an exception of the unspecified cast.
More about CollectionView can be found here: https://learn.microsoft.com/en-us/xamarin/xamarin-forms/user-interface/collectionview/layout#vertical-grid
Feel free to get back in case of queries.

Related

Xamarin Forms having trouble centering a collectionview

I have a collection view like so:
<CollectionView ItemsSource="{Binding subCategories}" ItemsLayout="HorizontalGrid, 3" IsVisible="{Binding isCollection}" HeightRequest="250" SelectionMode="Single" SelectionChanged="CollectionView_SelectionChanged" HorizontalOptions="FillAndExpand">
<CollectionView.ItemTemplate>
<DataTemplate>
<StackLayout Spacing="8" HorizontalOptions="FillAndExpand">
<Frame BorderColor="LightGray" HasShadow="True" HeightRequest="20" Margin="20" Padding="20">
<Label Text="{Binding name}" TextColor="#02cc9d" FontAttributes="Bold"></Label>
</Frame>
</StackLayout>
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
And this is the result:
There are 2 things I am trying to do here, the first is center this collection view, I have tried all the HorizontalOptions on the StackLayout and on the CollectionView. The other thing that I bothering me is when an item is selected, the grey box that appears to indicate an item is selected is also not centered, how do I fix this collection view to make it look nicer?
A HorizontalGrid layout is one that grows horizontally as needed. It may be difficult to center horizontally, because it is prepared to grow horizontally if you add more items.
Try ItemsLayout="VerticalGrid, 3".
If necessary, test with different layout options.
(OP says in comment that this fixed both problems.)

Xamarin - CollectionView extra space for first and last item

Hello guys,
my question is if I'am able to add some extra space above first item and under last item in CollectionView in Xamarin.
I have items styled like card with rounded corners but at the moment it can't be seen clearly because there is no space above first and under last item. Vertical space between them is okay with ItemSpacing property.
I will add screenshot here. The blackline is the exact place where I need space.
As jason said that you can add padding or Margin for Grid or stacklayout, then add CollectionView in this layout.
<Grid Padding="20">
<CollectionView ItemsSource="{Binding images}">
<CollectionView.ItemTemplate>
<DataTemplate>
<Frame BorderColor="Black" CornerRadius="30">
<StackLayout>
<Image Source="{Binding imagepath}" />
<Label Text="{Binding text}" />
</StackLayout>
</Frame>
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
</Grid>

Xamarin Forms Using multiple lists in ViewModel

I have a problem. I created a CollectionView with a ViewModel, in that ViewModel I have 2 different Lists. Now I know how to show data from 1 list, but now I want in the datatemplate a picker with the data of the second list. Here is the xaml code:
<CollectionView ItemsSource="{Binding imageList}">
<CollectionView.ItemsLayout>
<GridItemsLayout Orientation="Vertical" />
</CollectionView.ItemsLayout>
<CollectionView.ItemTemplate>
<DataTemplate>
<Picker Grid.Row="0" Grid.RowSpan="2" Grid.Column="3" Title="Formaat" ItemsSource="{Binding secondList}" HorizontalOptions="FillAndExpand" />
<Label Grid.Row="0" Grid.Column="4" VerticalTextAlignment="Center" VerticalOptions="Center"
HorizontalOptions="Center" Text="{Binding Price, StringFormat='€ {0:F2}'}" TextColor="Black"
FontSize="18" />
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
So the Price does get shown from the imageList, but the Picker is empty. In the Picker I want the element Name from the secondList
How can I fix this?
The problem is that your BindingContext in the DataTemplate of your CollectionView element is an item from your imageList. Therefore the binding will not work, as I assume your secondList is not a part of the element's model that you're using in the imageList but rather a part of the entire view model used for the page.
I would suggest using the RelativeBinding. I don't know the names of your models but your Picker binding could look like this:
<Picker ItemsSource="{Binding Source={RelativeSource AncestorType={x:Type local:YourViewModelTypeName}}, Path=secondList}" />

I am not able to access x:Name of controls in ListView in XAML and Code behind

I have a ListView in Xamarin forms which has a custom cell in it. The custom cell contains an Image control with a x:Name attribute. Now I tried to bind an activity indicator IsRunning Property to the Image IsLoading Property and Xamarin forms could not find the Image using the x:Name. I tried accessing from the backend too, same thing.
I added other elements in the Listview and their x:Name were not visible too.
NB: I can access x:Name of controls I put outside the ListView so it is looking like a listview issue.
<StackLayout>
<ActivityIndicator x:Name="activity" Color="Purple" HeightRequest="50" WidthRequest="50" IsRunning="{Binding Source={x:Reference Offerimg},Path=IsLoading}"></ActivityIndicator>
<ListView x:Name="OfferLV" HasUnevenRows="True" x:FieldModifier="Public" SeparatorVisibility="None" BackgroundColor="White">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell >
<StackLayout Padding="0,10,0,10">
<Image x:Name="offerimg" HeightRequest="500" WidthRequest="100" Aspect="AspectFill"></Image>
</StackLayout>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</StackLayout>
There is a very nice library FFImageLoading that will help you do what you want, and has a built in IsLoading property to display an ActivityIndicator accordingly. You can also handles loading error and so ...
<ListView VerticalOptions="StartAndExpand" ItemsSource="{Binding Items}">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<Grid>
<ff:CachedImage x:Name="Image" Source="https://www.allibert-trekking.com/uploads/media/images/thumbnails/AMin3_10-photo-montagne-chine-lac.jpeg?v2" />
<ActivityIndicator Color="OrangeRed" IsRunning="{Binding IsLoading}" IsVisible="{Binding IsLoading}" BindingContext="{x:Reference Name=Image}" />
</Grid>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
I created a sample for this example here : https://github.com/vincentcastagna/ImageLoadingPlaceHolder
That's how things are expected to work in XAML technologies including Xamarin.Forms.
There is not just a single ViewCell, but there could be thousands of them and you can't access thousands different items with one name.
Recommended way is to use data binding. Frequently you can also access those items by casting the sender in events.

Xamarin Listview with grouping won't scroll

I'm working on my first Xamarin app. I want to make a listview with grouping and it succeeded. The only problem I have that it won't scroll. My other listview on another page scrolls without a problem, but my listview with grouping won't do that. I tried this both on an Android simulator as on my Android phone (I don't have a macbook or something to test on iOS), and it won't scroll on either of them. I looked it up but a lot of people put the listview in a scrollview, and I didn't do that.
This is my XAML code:
<StackLayout Margin="10" Orientation="Vertical">
<Label Text="{Binding Title}" FontAttributes="Bold"
FontSize="20" HorizontalOptions="CenterAndExpand" />
<Label Text="{Binding Subtitle}" FontAttributes="Italic"
FontSize="15" HorizontalOptions="CenterAndExpand" />
<ListView HasUnevenRows="True" SeparatorColor="Accent"
VerticalOptions="FillAndExpand" IsEnabled="False"
IsGroupingEnabled="True" GroupDisplayBinding="{Binding Key}"
ItemsSource="{Binding ScansGroup}">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<StackLayout Spacing="4">
<StackLayout Orientation="Horizontal" Margin="10,7,10,1">
<Label Text="{Binding Location, StringFormat='{0}'}"
FontAttributes="Bold" FontSize="16" />
<Label Text="{Binding DateTime, StringFormat='{0:dd/MM/y HH:mm}'}"
HorizontalOptions="EndAndExpand" />
</StackLayout>
<StackLayout Orientation="Horizontal">
<Label Text="{Binding ElapsedTimeOnLocation}"
HorizontalOptions="Start"
Margin="10,0,10,7" />
</StackLayout>
</StackLayout>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</StackLayout>
I put it in an MVVM structure, and the grouping I did with a MVVM helper that I got from here https://channel9.msdn.com/Shows/XamarinShow/The-Xamarin-Show-12-MVVM-Helpers .
My code behind that is meant for the grouping is the following:
public ObservableRangeCollection<Grouping<string, ScanViewModel>> ScansGroup { get; } =
new ObservableRangeCollection<Grouping<string, ScanViewModel>>();
void Group()
{
var grouped = from scan in Scans
group scan by scan.Day into scanGroup
select new Grouping<string, ScanViewModel>(scanGroup.Key, scanGroup);
ScansGroup.ReplaceRange(grouped);
}
The grouping shows perfectly and the list too. The only problem is that
I can't scroll. Can someone help me?
I've figured it out. There's nothing wrong with your grouping. In your code you set IsEnabled="False" to the ListView. It makes the listview's scroll ability to be handled just if you drag from an enabled item inside the ListView, and even thus, the scroll is like belittled and with a very bad user experience.
Just set your ListView like this:
<ListView HasUnevenRows="True"
SeparatorColor="Accent"
VerticalOptions="FillAndExpand"
IsEnabled="True"
IsGroupingEnabled="True"
GroupDisplayBinding="{Binding Key}"
ItemsSource="{Binding ScansGroup}">
...
</ListView>
I can't tell you if it was designed to be this way, or if it 's a bug, but it is the cause of your issue.
It's probable you have done this to handle some unwanted behavior. If so, let us know what is specifically your intend with this IsEnabled="False", then we'll be able to help you with this.
I hope it helps you.
You didn't add the template for the group. Add this in the <ListView>
<ListView.GroupHeaderTemplate >
<DataTemplate >
<ViewCell Height="28" >
<Label Text="{Binding GroupName}" VerticalTextAlignment="Center" HorizontalOptions="Start" />
</ViewCell>
</DataTemplate>
</ListView.GroupHeaderTemplate>
Also, in the code bend or ViewModel, you need to bind to a group class of the items you want in the list such as:
public class GroupDetails : ObservableCollection<SomeItemsToShow>
{
public string GroupName { get; set; }
}
Check out this Example for more details:
https://xamarinhelp.com/xamarin-forms-listview-grouping/

Categories

Resources