Reuse listview templates - xaml

I am working on a Xamarin.Forms project. It has multiple pages with ListViews that display content that requires templates. How can I easily reuse one template thought the whole project because right now I have to update the templates on each page everytime I change something in one.
I have created a template as such in each page's xaml
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:*snip*.Renderers;assembly=*snip*"
x:Class="*snip*.MainPage">
<ContentPage.Resources>
<ResourceDictionary>
<DataTemplate x:Key="template1">
<local:PostViewCell>
<StackLayout BackgroundColor="White" Margin="10, 10, 10, 10" Padding="10, 10, 10, 10">
. . .
</StackLayout>
</local:PostViewCell>
</DataTemplate>
<DataTemplate x:Key="template2">
<local:PostViewCell>
<StackLayout BackgroundColor="White" Margin="10, 10, 10, 10" Padding="10, 10, 10, 10">
. . .
</StackLayout>
</local:PostViewCell>
</DataTemplate>
<local:PostTemplateSelector x:Key="templateSelector"
Template1="{StaticResource template1}"
Template2="{StaticResource template2}" ></local:PostTemplateSelector>
</ResourceDictionary>
</ContentPage.Resources>
<ContentPage.Content>
<StackLayout>
<local:PostListView x:Name="PostListView" ItemTemplate="{StaticResource templateSelector}"/>
</StackLayout>
</ContentPage.Content>

Define your Datatemplate with Unique key in App.Xaml Like,
<Application xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="YourAppName.App">
<Application.Resources>
<ResourceDictionary>
<DataTemplate x:Key="lstTemplate">
<ViewCell>
<------Your Design here------->
</ViewCell>
</DataTemplate>
</ResourceDictionary>
</Application.Resources>
</Application>
Use that lstTemplate key in your Listview Like,
<ListView x:Name=lst"
ItemsSource="{Binding Name}"
SeparatorColor="#0094FF" ItemTemplate="{StaticResource lstTemplate}">

You can define the DataTemplate as a resource in App.xaml and refer to it from individual XAML pages

Related

Hide frame in custom ContentView

I'm using a content view page called CardViewTemplate.xaml in my ListView to render some content with two frames, one of them should be visible and the other not, at the same time.
<ContentView xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
...>
<Frame IsVisible="{Binding IsNotBreak}" IsClippedToBounds="True">
.... content ....
</Frame>
<Frame IsVisible="{Binding IsBreak}" IsClippedToBounds="True">
--content 2-
</Frame>
</ContentView>
and the above page used in list view to bind and view some data to listview like below code:
<ListView x:Name="listView" SelectedItem="{Binding SelcetedItem,Mode=TwoWay}"
RowHeight="-1"
ItemsSource="{Binding SelectedCard}" HasUnevenRows="True" >
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<Custom:CardViewTemplate/>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</StackLayout>
Unexpectedly my list view shows only the second frame and it looks like attached image:
That is because ContentView is supposed to have only one child, and the second Frame is overriding the first Frame.
Try adding a view-container like AbsoluteLayout, or Grid to hold the two frame(s) inside ContentView:
<ContentView xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
...>
<AbsoluteLayout>
<Frame IsVisible="{Binding IsNotBreak}" IsClippedToBounds="True">
.... content ....
</Frame>
<Frame IsVisible="{Binding IsBreak}" IsClippedToBounds="True">
--content 2-
</Frame>
</AbsoluteLayout>
</ContentView>

XAML background color and text color not changing

I do not know if my code displays a list of FOOS .It does generate a list item that is clickable which goes to the correct Details page, the problem is the list item is either blank or all the text is white. I cannot figure out which.
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="MaopApplication.Views.PipelineSearch">
<StackLayout Orientation="Vertical">
<StackLayout Orientation="Horizontal" >
<Entry Placeholder="Search With PipelineName" Text="{Binding SearchText}" ></Entry>
<Button Text="Search" Command="{Binding SearchPipes}" />
</StackLayout>
<ListView ItemsSource="{Binding Foos}" ItemTapped="OnListViewItemTapped" ItemSelected="OnListViewItemSelected">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<ViewCell.View BackgroundColor="Red">
<StackLayout>
<label Text="wtf" TextColor="Black"></label>
<label Text="{Binding Test}"TextColor="Black"/>
</StackLayout>
</ViewCell.View>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</StackLayout>
</ContentPage>
CODE TO CREATE FOOS
var Foos = new List<object>() {new {Test = "foo"}, new {Test = "bar"}};
A couple things wrong here (maybe it was just a bad copy/paste job):
ViewCell.View does not have a BackgroundColor property, use StackLayout.BackgroundColor instead
label should be Label (capitals matter)
When I made those change to your code, it ran fine for me:
<ViewCell>
<ViewCell.View>
<StackLayout BackgroundColor="Red">
<Label Text="wtf" TextColor="Black"/>
<label Text="{Binding Test}" TextColor="Black"/>
</StackLayout>
</ViewCell.View>
</ViewCell>

Xamarin.Forms - x:Reference 2nd level

I'm currently working in a new ContentPage for my application and I have some controls with DataTemplates.
I would like to use a Command in my ContentPage's ViewModel in one of the DataTemplates, however I'm not sure how to do the right reference for this to work properly. Here's my XAML code:
<?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="MaverickMobileOnline.ImagesListingPage"
--MANY NAMESPACE REFERENCES--
>
<ContentPage.Resources>
<ResourceDictionary>
<c:ItemTappedEventArgsConverter x:Key="ItemTappedConverter" />
<c:ItemAppearingEventArgsConverter x:Key="ItemAppearingConverter" />
<c:BooleanNegationConverter x:Key="not" />
</ResourceDictionary>
</ContentPage.Resources>
<StackLayout Spacing="0">
<commonViews:MainCustomNavBar MinimumHeightRequest="120" />
<controls:PullToRefreshLayout
x:Name = "layout"
RefreshCommand="{Binding btn_reload_businesses_images_click}"
IsEnabled = "True"
IsRefreshing="{Binding Path=is_businesses_loading}" >
<ScrollView
x:Name = "scrollView"
HorizontalOptions="FillAndExpand"
VerticalOptions="FillAndExpand">
<templates:ItemsStack
Padding="0"
Margin="0,10,0,10"
x:Name="itmStack"
BackgroundColor="White"
ItemsSource="{Binding Path=photos_list}">
<templates:ItemsStack.ItemTemplate>
<DataTemplate>
<artina:GridOptionsView
Padding="10,0"
ColumnSpacing="10"
RowSpacing="10"
VerticalOptions="Fill"
HeightRequest="120"
ColumnCount="3"
RowCount="1"
ItemsSource="{Binding Path=.}">
<artina:GridOptionsView.ItemTemplate>
<DataTemplate>
<ContentView
xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="MaverickMobileOnline.GalleryImageItemTemplate"
xmlns:ffimageloading="clr-namespace:FFImageLoading.Forms;assembly=FFImageLoading.Forms"
xmlns:fftransformations="clr-namespace:FFImageLoading.Transformations;assembly=FFImageLoading.Transformations">
<ContentView.Content>
<ffimageloading:CachedImage
FadeAnimationEnabled="true"
Aspect="AspectFill"
VerticalOptions="FillAndExpand"
HorizontalOptions="FillAndExpand"
LoadingPlaceholder="advertising_photo_placeholder.png"
Source="{Binding Path=image_medium}" />
</ContentView.Content>
<ContentView.GestureRecognizers>
<TapGestureRecognizer
-- HERE! --
Command="{Binding Source={x:Reference X}, Path=BindingContext.command_name}"
CommandParameter="{Binding image_medium}"
/>
</ContentView.GestureRecognizers>
</ContentView>
</DataTemplate>
</artina:GridOptionsView.ItemTemplate>
</artina:GridOptionsView>
</DataTemplate>
</templates:ItemsStack.ItemTemplate>
</templates:ItemsStack>
</ScrollView>
</controls:PullToRefreshLayout>
</StackLayout>
</ContentPage>
Please take a look at the code after the mark "-- HERE! --".
PS: I'm just refining this layout on order to improve performance.
Any help will be appreciated.
UPDATE:
ViewModel:
public RelayCommand<string> btn_image_tap_preview
{
get
{
return new RelayCommand<string>(
OpenImagePreview
);
}
}
//* Image tap
private async void OpenImagePreview(string url)
{
//* Some code
}
Updated XAML:
<StackLayout x:Name="mainStack" Spacing="0">
<commonViews:MainCustomNavBar MinimumHeightRequest="120" />
....
<ContentView.GestureRecognizers>
<TapGestureRecognizer Command="{Binding Source={x:Reference mainStack}, Path=BindingContext.btn_image_tap_preview}"
CommandParameter="{Binding image_medium}" />
</ContentView.GestureRecognizers>
I'm debugging but I can't reach the ViewModel's command.
You can use x:Reference and take the binding context of any layout or element from your content page like StackLayout. Since its binding context is the ViewModel of the page it would have the command you are looking for at the first level itself. You can directly use it.
<StackLayout x:Name="myStackLayout" Spacing="0">
<commonViews:MainCustomNavBar MinimumHeightRequest="120" />
....
<ContentView.GestureRecognizers>
<TapGestureRecognizer Command="{Binding Source={x:Reference myStackLayout}, Path=BindingContext.command_name}"
CommandParameter="image_medium" />
</ContentView.GestureRecognizers>
Or you can set the binding context for TapGesture
<TapGestureRecognizer BindingContext="{Binding Source={x:Reference myStackLayout.BindingContext}}" Command="{Binding command_name}"
DataTemplates does not seem to work well with x:Reference prior to v1.4.4, you can read more about in the forum post - x:Reference not working?.
The implementation in the newer version can be seen in the answer here.
If you are interested the Bugzilla issue that was fixed is here.

The cell doesnt show a complete image

I want to do a Cell with a yellow background and one orange box with a text and after an image with a medium size, but it doesn't work. The image doesn't appear big and I can't use a margin
This is my XAML
<?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="neoFly_Montana.Views.PromocoesView"
BackgroundImage="promocoesbackground"
Title="Promoções">
<ContentPage.Content>
<ListView x:Name="listview_promocoes" Margin="0, 20, 0, 0 ">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<StackLayout BackgroundColor="AliceBlue" HorizontalOptions="Center" VerticalOptions="FillAndExpand">
<Label Text="{Binding titulo}" Style="{StaticResource labelsfont}"/>
<Image Source="{Binding imagem}" Aspect="AspectFill"/>
</StackLayout>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</ContentPage.Content>
This is the bad result (with 2 item - u can't see the image)
I want to do something like this but I can't use margin because when I use it, the app doesn't work.
It needs to be one item of a ListView.
All items should be like this.
How can I do that?
Thank you.
You can get that Layout in your ListView item with something like this:
<ListView
RowHeight="170"
ItemsSource="{Binding Items}">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<!-- Outter box containing two boxes -->
<StackLayout
VerticalOptions="FillAndExpand">
<!-- First box with Title, Image and Text -->
<StackLayout
VerticalOptions="FillAndExpand"
Padding="10, 5"
BackgroundColor="Yellow">
<Label
Text="YOUR_TITLE"
BackgroundColor="Silver"/>
<Image
HorizontalOptions="FillAndExpand"
BackgroundColor="Fuchsia"
HeightRequest="60" />
<Label
Text="YOUR_OTHER_TEXT"
BackgroundColor="Silver"/>
</StackLayout>
<!-- Second box with Text -->
<StackLayout
VerticalOptions="End"
Margin="0, 8, 0, 0"
Padding="10, 5"
BackgroundColor="Lime">
<Label
Text="YOUR_TEXT_OTHER_BOX"
BackgroundColor="Silver"/>
</StackLayout>
</StackLayout>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
I guess you might need to do a few little changes to get it exactly as you want it but this is pretty close.
Result:
Hope this helps.-

How to use a Frame as the root element of a ListView in Xamarin.Forms?

I am trying to achieve a list of Card-like records for the timeline on an application built in Xamarin.Forms, this is the layout that more or less I need to replicate:
I think I am close, I have two records on my code behind that I assign as the ItemSource to a listView on the XAML side, and this is my result so far:
But as you can see, the elements are not showing at all inside their frame, if I replace the form controls with TextCells or ImageCells, the data shows fine. This is the XAML code I have so far:
<?xml version="1.0" encoding="UTF-8"?>
<ContentPage Title="AudioBitts"
xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:AudioBitts"
x:Class="AudioBitts.TimelinePage">
<ListView x:Name="listView">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell Height="300">
<Frame HasShadow="true" Margin="5">
<StackLayout>
<StackLayout Orientation="Horizontal">
<Image Source="{Binding UserAvatar}" />
<Label Text="{Binding UserName}" />
</StackLayout>
<Image Source="{Binding BittImage}" />
</StackLayout>
</Frame>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</ContentPage>
Am I missing something on the structure I am giving to my XAML code? Thanks!
You can set ListView.RowHeight or set ListView.HasUnevenRow to allow the data to be displayed in full.