Add Grid to ItemTemplate in Xamarin.Forms - xaml

In a Xamarin Forms(MAUI) project I would like to add a Grid with some prices inside another Grid placed in a CollectionView
The Grid is like below and I have created a function which returns a Grid. This works fine in an ordinary stacklayout : where I create the grid and add it as a Child of PriceData.
How do i accomplish that in a ItemTemplate of a CollectionView at runtime placing the grid where the placeholder RIGHTHERE I WANT TO ADD A GRID are
<CollectionView.ItemTemplate>
<DataTemplate>
<Grid Padding="5" Margin="20,20,20,20" >
<Grid.GestureRecognizers>
<TapGestureRecognizer Command="{Binding Path=BindingContext.GotoDetailPage, Source={x:Reference Page}}" CommandParameter="{Binding .}" />
</Grid.GestureRecognizers>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="2*"></ColumnDefinition>
<ColumnDefinition Width="5*"></ColumnDefinition>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Image Grid.Column="0" Grid.Row="0" HorizontalOptions="CenterAndExpand" VerticalOptions="CenterAndExpand" Aspect="Fill" WidthRequest="60" HeightRequest="60" Source="{Binding .,Converter={StaticResource ImageConverter}}"></Image>
<StackLayout Grid.Column="1" Grid.Row="0">
<Label Text="{Binding Title}" />
<Label Text="{Binding BodyText}" />
<<RIGHTHERE I WANT TO ADD A GRID>>
</StackLayout>
<BoxView Grid.Row="1" Grid.ColumnSpan="2" HeightRequest="1" BackgroundColor="LightGray"/>
</Grid>
</DataTemplate>
</CollectionView.ItemTemplate>

Sorry if the question was unprecise.
The issue was to manipulate with a Grid placed in a CollectionView.ItemTemplate which was bound to a datasource.
I solved it by creating a ContentView with a StackLayout.
The model was passed as a BindableProperty and
then on propertyChanged I created a Grid and added it as a child of the StackLayout

Related

Is there a way for a ListView within Grid to inherit the grid's ColumnDefinitions & RowDefinitions?

I'm essentially trying to create a view that displays a list of items underneath an interactable header (a Button and an Image wrapped in a FlexLayout) that sorts that specific column A-Z / Z-A, my problem is that I can't figure out how to line them up neatly and without manually setting the column width in ColumnDefinition.
Normally I'd just set the width to some value but since its going to be cross platform (including tablets) I want to avoid doing that so I don't end up with everything squished to one side if the user decides to use a tablet with a much wider screen, does anyone know any fixes or have any advice on what I could look into trying?
Thanks in advance, and I'll post a snippet of what I'm trying to achieve below
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<FlexLayout AlignItems="Center" Grid.Row="0" Grid.Column="0">
<Button Text="Name" FontSize="8" Clicked="QuickSort" Padding="0"/>
<Image Source="" Aspect="AspectFit" HeightRequest="20" WidthRequest="20" IsVisible="False"/>
</FlexLayout>
<FlexLayout AlignItems="Center" Grid.Row="0" Grid.Column="1">
<Button Text="Type" FontSize="8" Clicked="QuickSort" Padding="0"/>
<Image Source="" Aspect="AspectFit" HeightRequest="20" WidthRequest="20" IsVisible="False"/>
</FlexLayout>
<FlexLayout AlignItems="Center" Grid.Row="0" Grid.Column="2">
<Button Text="Cost" FontSize="8" Clicked="QuickSort" Padding="0"/>
<Image Source="" Aspect="AspectFit" HeightRequest="20" WidthRequest="20" IsVisible="False"/>
</FlexLayout>
<ListView ItemSource="{Binding Collection}" Grid.Row="1">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<Label Text="{Binding name}" Grid.Column="0"/>
<Label Text="{Binding type}" Grid.Column="1"/>
<Label Text="{Binding cost}" Grid.Column="2"/>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</Grid>
A simple solution is to copy the Grid column declarations into the ItemTemplate's DataTemplate. This makes each item a Grid, whose columns match the outer Grid:
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<Grid ColumnDefinitions="*, *, *">
<Label Text="{Binding name}" Grid.Column="0"/>
<Label Text="{Binding type}" Grid.Column="1"/>
<Label Text="{Binding cost}" Grid.Column="2"/>
</Grid>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
The labels all default to "Row=0", so each item is a one-row Grid.
If you like to make it easier, maybe try some datagrid libraries like https://github.com/akgulebubekir/Xamarin.Forms.DataGrid

Xamarin iOS - How to get StackLayout to auto size to nested contents?

I have the following XAML :
<StackLayout>
<Grid IsVisible="{Binding isVisible}" VerticalOptions="FillAndExpand" HorizontalOptions="FillAndExpand">
<behaviors:Expander x:Name="MainExpander" CollapseAnimationLength="500" IsExpanded="false" >
<behaviors:Expander.Header>
<Grid HorizontalOptions="FillAndExpand">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="100"/>
<ColumnDefinition Width="10"/>
</Grid.ColumnDefinitions>
<Frame HeightRequest="40" WidthRequest="40" CornerRadius="20" HorizontalOptions="Start" VerticalOptions="Center" Margin="20" Padding="0" BackgroundColor="Maroon">
<Label Text="{Binding student_initial}" TextColor="White" HorizontalOptions="Center" VerticalOptions="Center" HorizontalTextAlignment="Center" VerticalTextAlignment="Center" />
</Frame>
<StackLayout Grid.Column="2" HorizontalOptions="StartAndExpand" VerticalOptions="Center" Margin="20">
<Label x:Name="StudentName" Text="{Binding student_fullname}"></Label>
<Label x:Name="StudentID" IsVisible="false" Text="{Binding student_unique_id}"></Label>
</StackLayout>
</Grid>
</behaviors:Expander.Header>
<Grid RowSpacing="0" HorizontalOptions="FillAndExpand" HeightRequest="240" VerticalOptions="FillAndExpand">
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="*"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Button Grid.Row="0" Text="Messages" Clicked="Button_Clicked"></Button>
<Button x:Name="btnTopUp" Grid.Row="1" Text="Quick Topup" Clicked="Button_Clicked" IsVisible="{Binding topup_product_id, Converter={StaticResource IsNotNullOrEmptyConverter}}"></Button>
<Button Grid.Row="2" Text="Payments" Clicked="Button_Clicked"></Button>
</Grid>
<!--TODO: Look at adding a balance for childrens topups?-->
</behaviors:Expander>
</Grid>
</StackLayout>
I am trying to hide and show the grid as follows :
<Grid IsVisible="{Binding isVisible}" ...
The issue is that nothing shows as it looks like the StackLayout is unable to work out how high it needs to be. I can't explicitly set the height property as it depends if the expander is expanded or not. Is there a way to make the stack layout height auto size ? Thank you.
Replace StackLayout with Grid , set its HorizontalOptions and VerticalOptions as Start .
<Grid BackgroundColor="Red" HorizontalOptions="Start" VerticalOptions="Start">
<Grid IsVisible="false" ...
See the following screen shot in all of the scenarios (red color represents the root Grid)
Gird invisible
Grid visible (none-expanded)
Grid visible (expanded)

Label TextColor Binding in DataTamplate xaml Xamarin

I do have a CollectionView with a binding for the text in the labels. This works without a problem.
But now I want to add a binding for the Text Color and I don't know how to do it.
my xaml:
<CollectionView ItemsSource="{Binding List}" SelectionMode="None">
<CollectionView.ItemTemplate>
<DataTemplate>
<ScrollView>
<Grid Padding="10">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<Label Text="{Binding AttributFromListObject}" TextColor="{Binding TextColor}" Grid.Row="0" Grid.Column="0"/>
<
</Grid>
</ScrollView>
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
I have set the bindingcontext in the codebehind.
In a normal label without the DataTemplate, the binding TextColor is working.
How can I tell the xaml that it should use the bindingcontext of the page for the TextColor?
Thanks for your help!
#Json comment had the answer.
Needed to add the following
xmlns:ViewModels="clr-namespace:AppName.ViewModels"
TextColor="{Binding Source={RelativeSource AncestorType={x:Type ViewModels:MyViewModel}}, Path=TextColor}"

Xamarin - CollectionView, pass current item as a command parameter

I Have a CollectionView which is bound to an ObservableCollection, inside each row of the view i have a (LIKE/UNLIKE) button, when that button is clicked, a command on the ViewModel is called, which should read the ID + state (button checked/unchecked) to determine if it should execute a LIKE or UNLIKE API call.
My question is, how do i pass the current item (parent row of the button) as a command parameter (of type Product) ?
Here is my XAML:
<CollectionView ItemsSource="{Binding Products}" SelectionMode="Single" SelectedItem="{Binding SelectedProduct , Mode=TwoWay}" RemainingItemsThreshold="{Binding ItemsThreshold}" RemainingItemsThresholdReachedCommand="{Binding LoadProductsCommand}" BackgroundColor="Fuchsia">
<CollectionView.ItemsLayout>
<GridItemsLayout Orientation="Vertical" VerticalItemSpacing="10"></GridItemsLayout>
</CollectionView.ItemsLayout>
<CollectionView.ItemTemplate>
<DataTemplate>
<Frame BorderColor="Black" BackgroundColor="Green" HeightRequest="100" Padding="0" Margin="0 , 10" HasShadow="True">
<Grid Padding="0">
<Grid.RowDefinitions>
<RowDefinition Height="*"></RowDefinition>
<RowDefinition Height="*"></RowDefinition>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"></ColumnDefinition>
<ColumnDefinition Width="*"></ColumnDefinition>
</Grid.ColumnDefinitions>
<Image Source="{Binding photo_1}" Aspect="AspectFill" Grid.Row="0" Grid.Column="0"></Image>
<StackLayout Grid.Row="1" Grid.Column="1" BackgroundColor="Yellow" HorizontalOptions="End">
<button:SfButton Text="HEART" IsCheckable="True" IsChecked="{Binding liked}" Command="{Binding Source={x:Reference MyProductsPage} , Path=BindingContext.LikeCommand}" CommandParameter="{Binding ???}"></button:SfButton>
<Label Text="{Binding total_likes}" HorizontalTextAlignment="Center"></Label>
</StackLayout>
</Grid>
</Frame>
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
Just binding like this:
<button:SfButton Text="HEART" IsCheckable="True" IsChecked="{Binding liked}" Command="{Binding Source={x:Reference MyProductsPage} , Path=BindingContext.LikeCommand}" CommandParameter="{Binding .}"></button:SfButton>
Here is the code example: ContactView

ListView with grid where padding causes child elements to shrink

I'm currently styling a listview, in which I want to add a separating space between each entity in the ListView. For doing that, I use a Grid for each ViewCell with Margin="0,0,0,10".
I can get my elements to fit inside the grid row, but if I add a padding to the row, to give it some top/bottom spacing, it just scales down the text inside the grid.rowuntil eventually, it disappears.
<ListView Margin="10" HasUnevenRows="false" BackgroundColor="Fuchsia" x:Name="deviceList" ItemsSource="{Binding Devices}" CachingStrategy="RecycleElement" SeparatorVisibility="None">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<ViewCell.View>
<Grid BackgroundColor="Silver" Margin="0,0,0,10">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<Grid Grid.Row="0" Grid.Column="0" VerticalOptions="Center" RowSpacing="10">
<local:IconView Source="BLE.png" Foreground="#3b5998" WidthRequest="30" HeightRequest="30" />
</Grid>
<Grid Grid.Row="0" Grid.Column="1" VerticalOptions="Center">
<Label Text="{Binding Name}" TextColor="Black" />
</Grid>
</Grid>
</ViewCell.View>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
How do I add padding to my Grid.Row without scaling down the child elements?