Carousal view with multiple items without databinding - xaml

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"

Related

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>

<Button Text="{Binding .}"/> doesn't work as intended

I have a CollectionView where the ItemsSource is bound with a List. The contents of this list should be displayed in the Text of the Button. To do this I use Text={Binding .}.
When the page loads, I get empty buttons with no text. If I then remove the . and retype it in the {Binding .}, the text will appear in my buttons.
Can someone explain this to me or explain what I'm doing wrong?
.xaml
<StackLayout>
<CollectionView x:Name="ItemsListView" ItemsSource="{Binding CurrentQuizItem.Answers}" SelectionMode="None">
<CollectionView.ItemTemplate>
<DataTemplate>
<StackLayout >
<Button Text="{Binding .}" Command="{Binding Source={RelativeSource AncestorType={x:Type viewmodel:TakeQuizPageViewModel}}, Path=AnswerClickedCommand}" Style="{StaticResource AnswerButton}"/>
</StackLayout>
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
</StackLayout>

Get SelectedItem from a nested RepeaterView

I am using DottorPagliaccius repeater view thats nested inside another repeaterview. The command RSSFeedSelectedCommand doesnt work unless on top repeater, which in theory makes sense but how can i get it to work?
I have looked into using Converters and bindtoeventcommand but cant see to get them working.
<repeater:RepeaterView x:Name="MainRepeater" SeparatorHeight="25" ItemsSource={Binding Feeds}">
<repeater:RepeaterView.ItemTemplate>
<DataTemplate>
<ViewCell>
<StackLayout Spacing="10">
<Label Text="{Binding Title}" TextColor="Blue" />
<Label Text="{Binding Description}" TextColor="Red" FontSize="12" />
<repeater:RepeaterView x:Name="MainRepeater2" EmptyText="No elements" ShowSeparator="true" SeparatorHeight="2" SeparatorColor="Silver" ItemsSource="{Binding Items}" SelectedItemCommand="{Binding RSSFeedSelectedCommand}">
<repeater`enter code here`:RepeaterView.ItemTemplate>
<DataTemplate>
<ViewCell>
<StackLayout Orientation="Horizontal">
<Image Source="{Binding Image.Url}"></Image>
<StackLayout Orientation="Vertical">
<Label Text="{Binding Title}" TextColor="Black" />
<Label Text="{Binding Description}" TextColor="Black" FontSize="12" />
</StackLayout>
</StackLayout>
</ViewCell>
</DataTemplate>
</repeater:RepeaterView.ItemTemplate>
</repeater:RepeaterView>
</StackLayout>
</ViewCell>
</DataTemplate>
</repeater:RepeaterView.ItemTemplate>
</repeater:RepeaterView>
The Repeater was trying to find the command in Feeds however exists in the ViewModel.
<repeater:RepeaterView x:Name="MainRepeater2" EmptyText="No elements" ShowSeparator="true" SeparatorHeight="2" SeparatorColor="Silver" ItemsSource="{Binding Items}" SelectedItemCommand="{Binding Source={x:Reference RSSPage}, Path=BindingContext.RSSFeedSelectedCommand}">
and you have to name the page:
<ContentPage x:Name="PageName" />
If my assumption is correct, your class structure should be something like,
ViewModel
|__List of Feeds
|__List of Items
|__RSSFeedSelectedCommand
So, DataContext of your inner repeater control (MainRepeater2) will be Feed. So, try with DataContext of outer repeater control. Like,
<repeater:RepeaterView x:Name="MainRepeater2" ItemsSource="{Binding Items}"
SelectedItemCommand="{Binding DataContext.RSSFeedSelectedCommand,
ElementName=MainRepeater}"/>
For Xamarin:
<repeater:RepeaterView x:Name="MainRepeater2" ItemsSource="{Binding Items}"
SelectedItemCommand="{Binding DataContext.RSSFeedSelectedCommand,
Source={x:Reference MainRepeater}}"/>

Using TextCell in a StackLayout in a ListView

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>

How to set margin around ImageCell in Xamarin.Forms?

I want to have some space around the Image cell items of a ListView:
<StackLayout>
<ListView ItemsSource="{Binding Items}" HasUnevenRows="True">
<ListView.ItemTemplate>
<DataTemplate>
<ImageCell Text="{Binding Title}" ImageSource="{Binding Image}" TextColor="Black" DetailColor="Gray"/>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</StackLayout>
but there's no Margin property available for the ImageCell?
EDIT
I did what cvanbeek suggested before posting the question:
<DataTemplate>
<StackLayout Padding="5">
<ImageCell Text="{Binding Title}" ImageSource="{Binding Image}" TextColor="Black" DetailColor="Gray"/>
</StackLayout>
</DataTemplate>
but I got this exception:
Unhandled Exception:
System.InvalidCastException: Specified cast is not valid.
in the OnCreate method in MainActivity.cs
DataTemplate definition
Only View can be put inside DataTemplate, however StackLayout is Layout.
Use a ViewCell instead , it is more flexible and controllable.
<ListView >
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<StackLayout Padding="20" Orientation="Horizontal" >
<Label Margin="20" Text="123"/>
<Image Source="Assets/StoreLogo.png"/>
</StackLayout>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>