Using TextCell in a StackLayout in a ListView - xaml

Why can I not use a TextCell like this in a ListView item template? When I use it the rows render but they are empty.
<ListView ItemsSource="{Binding Courses}">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<StackLayout Orientation="Vertical">
<TextCell Text="{Binding Title}" Detail="{Binding SubTitle}"></TextCell>
</StackLayout>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
When using a Label I can see the text contents in each row:
<ListView ItemsSource="{Binding Courses}">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<StackLayout Orientation="Vertical">
<Label Text="{Binding Title}"></Label>
<Label Text="{Binding SubTitle}"></Label>
</StackLayout>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
Is there anyway I can use the TextCell inside the list item template? I am trying to build a more complext layout inside the StackLayout and it would be greatly simplified if I could re-use the Title/Detail structure of the TextCell.

According to the Xamarin.Forms Cell Reference, cells are only designed to be added to ListViews or TableViews. In particular, it says:
However Cell is not a visual element, it just describes a template for
creating a visual element.
So it cannot be added directly to the children of a StackLayout. You will have to create a ViewCell with a custom template for that.. You can probably look at the source code on Github to find out the proper spacing that a TextCell uses between it's Text and TextDetail labels, to keep it consistent.

You Can Use Stack Layout in a text cell!
Here is the way for using it.
<TextCell>
<TextCell.BindingContext>
<StackLayout Orientation="Horizontal" >
<Label Text="{Binding Name}"
HorizontalOptions="CenterAndExpand" TextColor="Black"/>
<Label Text="{Binding Description}"
HorizontalOptions="CenterAndExpand" TextColor="Black"/>
<Label Text="{Binding Price}"
HorizontalOptions="CenterAndExpand" TextColor="Black"/>
</StackLayout>
</TextCell.BindingContext>
</TextCell>

Related

Carousal view with multiple items without databinding

How do I set static text as Carousal view items instead of doing data binding? Here in the below code I am trying to have Page 2 appear when the user swipes to the left. This code says The property ItemTemplate is set more than once
<StackLayout Margin="10">
<CarouselView>
<CarouselView.ItemTemplate>
<DataTemplate>
<Grid>
<Label Text="Page 1"/>
</Grid>
</DataTemplate>
</CarouselView.ItemTemplate>
<CarouselView.ItemTemplate>
<DataTemplate>
<Grid>
<Label Text="Page 2"/>
</Grid>
</DataTemplate>
</CarouselView.ItemTemplate>
</CarouselView>
</StackLayout>
If you want to set the items statically in xaml itself without data binding you can use Array markup extension of type string:
<StackLayout Margin="10">
<CarouselView>
<CarouselView.ItemsSource>
<x:Array Type="{x:Type sys:String}">
<sys:String>Page 1</sys:String>
<sys:String>Page 2</sys:String>
</x:Array>
</CarouselView.ItemsSource>
<CarouselView.ItemTemplate>
<DataTemplate>
<Grid>
<Label Text="{Binding .}" />
</Grid>
</DataTemplate>
</CarouselView.ItemTemplate>
</CarouselView>
</StackLayout>
PS: Don't forget to add the required xaml namespace:
xmlns:sys="clr-namespace:System;assembly=mscorlib"

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

I have a ListView in Xamarin forms which has a Viewcell in it. The Viewcell contains an lable control with a x:Name attribute. Now I tried to x:name in code behind but it is showing compile time error(The x:name does not exists in current context).
The below code im using.
<ListView x:Name="UnPaidInvoicesList"
SeparatorVisibility="None" IsPullToRefreshEnabled="True"
HasUnevenRows="True"
ItemSelected="UnPaidInvoicesList_ItemSelected"
VerticalOptions="FillAndExpand">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell >
<StackLayout x:Name="stkDuedate" Orientation="Horizontal">
<Label x:Name="lblDueDate1" Text="Due Date:" TextColor="Gray" />
<Label x:Name="lblDueDate" TextColor="{StaticResource Pink}" />
</StackLayout>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>```
Im new to this xamarin forms. Please help on this.
What features do you want to implement?
Just as Jason said,elements inside a template cannot be referenced by name.
If you want to disply a data list , you can bind the data to a ListView.
For this, you can refer to the following code:
<ListView x:Name="lstView" RowHeight="60" ItemsSource="{Binding veggies}" HasUnevenRows="True" IsPullToRefreshEnabled="False" SelectionMode="None">
<ListView.ItemTemplate >
<DataTemplate>
<ViewCell>
<StackLayout Orientation="Horizontal" HorizontalOptions="Fill" BackgroundColor="Olive">
<StackLayout Orientation="Vertical">
<Label Text = "{Binding Name}" FontSize="24" AbsoluteLayout.LayoutBounds="0.25, 0.25, 400, 40"/>
<Label Text = "{Binding Type}" AbsoluteLayout.LayoutBounds="50, 35, 200, 25"/>
</StackLayout>
<Image Source="{Binding Image}" HorizontalOptions="End" AbsoluteLayout.LayoutBounds="250.25, 0.25, 50, 50 "/>
</StackLayout>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
For more,you can check document Xamarin.Forms ListView and
Customizing ListView Cell Appearance.
You can also check the sample Xamarin.Forms - ListView Sample: Custom Cells.

Conditional text in Xamarin Forms

How do I conditionally render a particular text in Xamarin Forms 5?
For example, I get some data from my API backend for a vendor and there may be an address in the database for this vendor or not.
If I do have vendor's address, I'd like to display it and if I don't have an address, I'd like to display something like "n/a".
Is there a way to handle this in the XAML page or do I have to handle it in code behind?
UPDATE:
Here's what the XAML page for the phone numbers ListView looks like:
<Grid Grid.Row="1" Grid.Column="0" RowDefinitions="150, *" ColumnDefinitions="250, 250">
<StackLayout
Grid.Row="0"
Grid.Column="0"
Padding="10">
<ListView
BackgroundColor="Transparent"
SeparatorVisibility="None"
ItemsSource="{Binding Contact.PhoneNumbers, TargetNullValue='n/a'}">
<ListView.Header>
<StackLayout>
<Label Text="Phone Number(s)"
FontAttributes="Bold"/>
</StackLayout>
</ListView.Header>
<ListView.ItemTemplate>
<DataTemplate>
<TextCell Text="{Binding PhoneNumberDisplay}" />
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</StackLayout>
</Grid>
You can use xaml binding with TargetNullValue
<Label Text="{Binding Location, TargetNullValue='n/a'}"/>
If you don't have an address your API or your code should set Location to null in order for TargetNullValue to work.
Update (reply to this comment).
Use TargetNullValue in the bindings inside ItemTemplate (applies to each single element) and not on itemsource binding:
<Grid Grid.Row="1" Grid.Column="0" RowDefinitions="150, *" ColumnDefinitions="250, 250">
<StackLayout
Grid.Row="0"
Grid.Column="0"
Padding="10">
<ListView
BackgroundColor="Transparent"
SeparatorVisibility="None"
ItemsSource="{Binding Contact.PhoneNumbers}">
<ListView.Header>
<StackLayout>
<Label Text="Phone Number(s)"
FontAttributes="Bold"/>
</StackLayout>
</ListView.Header>
<ListView.ItemTemplate>
<DataTemplate>
<TextCell Text="{Binding PhoneNumberDisplay, TargetNullValue='n/a'}" />
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</StackLayout>
</Grid>

Xamarin Forms ListView Data Binding

ObservableCollection<string> CompanyList in the xaml.cs code behind is tied to <ListView> element in the xaml. Left alone, it displays a list of the strings in CompanyList as expected.
However, I want to customize (purely for style purposes) the ViewCell in the ListView while leaving CompanyList as a collection of strings. I am unsure how to bind the string company list value.
<ListView x:Name="CompanyList" ItemTapped="OnAddCompanyFilterTapped" >
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<StackLayout Padding="0" Spacing="0">
<StackLayout Padding="10">
<Label Text="{Binding ??????????}" HorizontalOptions="Fill"/>
</StackLayout>
<BoxView Style="{StaticResource divider}"/>
</StackLayout>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
What do I put in the ??????? to get the string in CompanyList to show?
Any help/suggestions/ideas is greatly appreciated!
Binding Path=. should do it, which can be shortened:
<Label Text="{Binding}" HorizontalOptions="Fill"/>
Assumes the ListView.ItemsSource remains CompanyList.

Xamarin.Forms Vertical StackLayout in ListView displays only one (first) Child

<ListView
ItemsSource="{Binding Messages}"
Grid.ColumnSpan="2"
HeightRequest="100">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<ViewCell.View>
<StackLayout>
<Label
Text="{Binding When}"
XAlign="Center"/>
<StackLayout
BackgroundColor="Gray"
Orientation="Vertical"
VerticalOptions="Center">
<Label
Text="{Binding Message}"
XAlign="Start"/>
<Label
Text="{Binding Sender}"
XAlign="Start"
TextColor="Red"/>
</StackLayout>
</StackLayout>
</ViewCell.View>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
I am rendering a custom ListView in Xamarin.Forms application. The StackLayout which contains two Labels (to which "Message" and "Sender" has been bound), currently displays only one child. With the code above, it displays only "Message". If I change code to be
<StackLayout
BackgroundColor="Gray"
Orientation="Vertical"
VerticalOptions="Center">
<Label
Text="{Binding Sender}"
XAlign="Start"
TextColor="Red"/>
<Label
Text="{Binding Message}"
XAlign="Start"/>
</StackLayout>
it displays only sender. In short it is displaying only first child. What have I done wrong here ?
Issue was similar to what #Grisha had pointed out. RowHeight was proving to be lesser, and the second StackLayout was getting clipped.
The solution was to set HasUnevenRows property of the ListView to be TRUE. Thus, RowHeight was calculated automatically.