I have a mobile app with Xamarin.Forms and FreshMvvm. Every page uses a control template defined in App.xaml:
<ControlTemplate x:Key="MainPageTemplate">
<Grid BindingContext="{Binding Source={RelativeSource TemplatedParent}}">
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="9*" />
</Grid.RowDefinitions>
<Image Source="{local:ImageResource MyApp.Images.My_logo.jpg}" Margin="0, 0, 0, 5" Grid.Row="0" />
<Label Text="{Binding ScreenName}" FontSize="Subtitle" TextColor="Black" FontAttributes="Bold" HorizontalOptions="Center" Grid.Row="1" />
<Label Text="{Binding ErrorMessage}" TextColor="Red" Grid.Row="2" />
<ContentPresenter Margin="10, 0, 10, 10" Grid.Row="3" />
</Grid>
</ControlTemplate>
The ScreenName property is defined in the PageModel like this:
protected string _screenName;
public string ScreenName => _screenName;
For some reason, the ScreenName is not showing up on the page that uses the control template. It does if I replace the Binding with a hard-coded text:
<Label Text="Something" ...
When setting your BindingContext to your {RelativeSource TemplatedParent}, your binding context is the page.
To access your ViewModel, you must change your xaml to access your property through the "BindingContext" of your page.
<Label Text="{Binding BindingContext.ScreenName}" FontSize="Subtitle" TextColor="Black" FontAttributes="Bold" HorizontalOptions="Center" Grid.Row="1" />
Related
In MVC ASP.net Core, I used partials to re-use blocks of a page. In Xamarin, we have DataTemplates & ControlTemplates but I'm not sure how to best use them.
In one of my pages I have the following for the content:
<StackLayout>
<Frame BackgroundColor="#2196F3" Padding="24" CornerRadius="0">
<Label Text="Welcome to data template selector" HorizontalTextAlignment="Center" TextColor="White" FontSize="36"/>
</Frame>
<CollectionView ItemsSource="{Binding MainPageView.Fields}"
EmptyView="No fields for this screen."
ItemTemplate="{StaticResource templateSelector}"
SelectionChanged="CollectionView_SelectionChanged">
</CollectionView>
<StackLayout Margin="10,0,10,5" Orientation="Vertical">
<Button Command="{Binding MainPageView.SubmitCommand}" Text="Submit" />
<validator:ErrorSummaryView
IsVisible="{Binding MainPageView.ShowValidationSummary, Mode=OneWay}"
ErrorStateManager="{Binding MainPageView.ErrorStateManager, Mode=OneWay}"
Margin="0,0,0,5"/>
</StackLayout>
</StackLayout>
The template selector is (there will be more choices later):
<tempcel:FieldDataTemplateSelector
x:Key="templateSelector"
RadioTemplate="{StaticResource RadioTemplate}"
DropListTemplate="{StaticResource DropListTemplate}">
</tempcel:FieldDataTemplateSelector>
Where I could use some direction is right now 80% of what is in RadioTemplate and DropListTemplate are the same and I'd like to pull the shared code out so if I want to change the base layout, I only need to change one place. Here are the two DataTemplates:
<DataTemplate x:Key="DropListTemplate">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<StackLayout
Orientation="Horizontal"
Grid.Row="0">
<Label
Text="{Binding Name}"
Style="{StaticResource LabelStyle}">
</Label>
<ImageButton HorizontalOptions="Center"
CornerRadius="6"
VerticalOptions="Center"
Clicked="HelpButton_Clicked"
HeightRequest="12"
WidthRequest="12"
BorderColor="Black"
BackgroundColor="Black"
BorderWidth="1"
IsVisible="{Binding ShowHelpButton}">
<ImageButton.Source>
<FontImageSource FontFamily="FAFreeSolid"
Color="White"
Glyph="{x:Static fa:FontAwesomeIcons.Question}"/>
</ImageButton.Source>
</ImageButton>
</StackLayout>
<Label
Grid.Row="1"
Style="{StaticResource HelpStyle}"
Text="{Binding HelpTopic.Text}"
IsVisible="{Binding HelpTopic.IsVisible, Mode=TwoWay}">
</Label>
<Picker
Grid.Row="2"
IsEnabled="{Binding IsEnabled}"
Margin="10,2,10,0"
ItemsSource="{Binding Choices.Choices}"
SelectedItem="{Binding SelectedChoice}"
ItemDisplayBinding="{Binding Label}"
SelectedIndexChanged="Picker_SelectedIndexChanged">
</Picker>
<validator:ErrorView ErrorState="{Binding ErrorStatemanager[Input]}" Grid.Row="3" />
</Grid>
</DataTemplate>
<DataTemplate x:Key="RadioTemplate">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<StackLayout
Orientation="Horizontal"
Grid.Row="0">
<Label
Text="{Binding Name}"
Style="{StaticResource LabelStyle}">
</Label>
<ImageButton HorizontalOptions="Center"
CornerRadius="6"
VerticalOptions="Center"
Clicked="HelpButton_Clicked"
HeightRequest="12"
WidthRequest="12"
BorderColor="Black"
BackgroundColor="Black"
BorderWidth="1"
IsVisible="{Binding ShowHelpButton}">
<ImageButton.Source>
<FontImageSource FontFamily="FAFreeSolid"
Color="White"
Glyph="{x:Static fa:FontAwesomeIcons.Question}"/>
</ImageButton.Source>
</ImageButton>
</StackLayout>
<Label
Grid.Row="1"
Style="{StaticResource HelpStyle}"
Text="{Binding HelpTopic.Text}"
IsVisible="{Binding HelpTopic.IsVisible, Mode=TwoWay}">
</Label>
<StackLayout
Grid.Row="2"
RadioButtonGroup.GroupName="{Binding Choices.Code}"
RadioButtonGroup.SelectedValue="{Binding Value}"
BindableLayout.ItemsSource="{Binding Choices.Choices}"
BindableLayout.EmptyView="No choices available"
Orientation="Horizontal"
Spacing="50"
Margin="10,2,0,0">
<BindableLayout.ItemTemplate>
<DataTemplate>
<RadioButton Value="{Binding Value}"
Content="{Binding Label}"
IsChecked="{Binding IsSelected}"
CheckedChanged="OnRadioChanged">
</RadioButton>
</DataTemplate>
</BindableLayout.ItemTemplate>
</StackLayout>
<validator:ErrorView ErrorState="{Binding ErrorStatemanager[Input]}" Grid.Row="3" />
</Grid>
</DataTemplate>
I haven't figured out enough about Xamarin to know if I need to change where I have the CollectionView to put something there that has the common layout information with a way to put the different editors in. Or, if there is a way to modify the DataTemplates to get their base layout from something else. I tried looking at ContentPresenter but couldn't figure out how it would fit in.
Thanks
I found there is very little difference between DropListTemplate and RadioTemplate. So you can also achieve this without DropListTemplate and RadioTemplate .
You can display and hide the two views (Picker and BindableLayout) based on the item data of the CollectionView 's ItemsSource.
The following are the difference in the two Templates:
<Picker
Grid.Row="2"
IsEnabled="{Binding IsEnabled}"
Margin="10,2,10,0"
ItemsSource="{Binding Choices.Choices}"
SelectedItem="{Binding SelectedChoice}"
ItemDisplayBinding="{Binding Label}"
SelectedIndexChanged="Picker_SelectedIndexChanged">
</Picker>
and
<StackLayout
Grid.Row="2"
RadioButtonGroup.GroupName="{Binding Choices.Code}"
RadioButtonGroup.SelectedValue="{Binding Value}"
BindableLayout.ItemsSource="{Binding Choices.Choices}"
BindableLayout.EmptyView="No choices available"
Orientation="Horizontal"
Spacing="50"
Margin="10,2,0,0">
<BindableLayout.ItemTemplate>
<DataTemplate>
<RadioButton Value="{Binding Value}"
Content="{Binding Label}"
IsChecked="{Binding IsSelected}"
CheckedChanged="OnRadioChanged">
</RadioButton>
</DataTemplate>
</BindableLayout.ItemTemplate>
</StackLayout>
I am trying to create a custom keyboard below is the xaml for the view, after all configuration it shows a blank page.
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms" xmlns:local="clr-namespace:CustomKeyboard" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" x:Class="CustomKeyboard.MainPage" Title="Custom Keyboard App" BackgroundColor="White">
<ScrollView>
<Grid Padding="15">
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="*" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Entry Grid.Row="0" HorizontalOptions="FillAndExpand" VerticalOptions="Start" Placeholder="Regular entry..." />
<StackLayout Grid.Row="1" Orientation="Vertical">
<local:EntryWithCustomKeyboard x:Name="entry1" HorizontalOptions="FillAndExpand" Margin="0, 0, 0, 20" Keyboard="Text" TextColor="Black" Placeholder="Custom Keyboard entry..." />
<local:EntryWithCustomKeyboard x:Name="entry2" HorizontalOptions="FillAndExpand" Keyboard="Text" TextColor="Black" Placeholder="Custom Keyboard entry 2..." />
</StackLayout>
<BoxView Grid.Row="2" />
</Grid>
</ScrollView>
</ContentPage>
I am trying to create a scrollable tabs in Xamarin.Forms with CollectionView and CarouselView as specified in this link. I need to load different ContentView in CarouselView based on the Tab selected in the header.
I tried like below but the ContentView is not displaying..
Below is xaml Code:
<Grid x:DataType="{x:Null}" RowSpacing="0">
<Grid.RowDefinitions>
<RowDefinition Height="45" />
<RowDefinition Height="45" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<CollectionView
x:Name="CustomTabsView"
Grid.Row="1"
HorizontalScrollBarVisibility="Never"
ItemSizingStrategy="MeasureAllItems"
ItemsSource="{Binding TabVms}"
ItemsUpdatingScrollMode="KeepItemsInView"
SelectedItem="{Binding CurrentTabVm, Mode=TwoWay}"
SelectionMode="Single"
VerticalScrollBarVisibility="Never">
<CollectionView.ItemsLayout>
<LinearItemsLayout Orientation="Horizontal" />
</CollectionView.ItemsLayout>
<CollectionView.ItemTemplate>
<DataTemplate x:DataType="local:TabViewModel">
<Grid RowSpacing="0">
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="3" />
</Grid.RowDefinitions>
<Label
x:Name="TitleLabel"
Grid.Row="0"
Padding="15,0"
FontAttributes="Bold"
FontSize="Small"
HeightRequest="50"
HorizontalTextAlignment="Center"
Text="{Binding Title}"
TextColor="White"
VerticalTextAlignment="Center" />
<BoxView
x:Name="ActiveIndicator"
Grid.Row="1"
BackgroundColor="Red"
IsVisible="{Binding IsSelected, Mode=TwoWay}" />
</Grid>
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
<CarouselView
Grid.Row="2"
CurrentItem="{Binding CurrentTabVm, Mode=TwoWay}"
CurrentItemChanged="CarouselView_CurrentItemChanged"
HorizontalScrollBarVisibility="Never"
IsScrollAnimated="True"
IsSwipeEnabled="True"
ItemsSource="{Binding TabVms}"
VerticalScrollBarVisibility="Never">
<CarouselView.ItemTemplate>
<DataTemplate x:DataType="local:TabViewModel">
<ContentView
x:Name="dynamiccontent"
BackgroundColor="White"
Content="{Binding DynamicContentView, Mode=TwoWay}" />
</DataTemplate>
</CarouselView.ItemTemplate>
</CarouselView>
</Grid>
.cs file Code
private void CarouselView_CurrentItemChanged(object sender, CurrentItemChangedEventArgs e)
{
var x = e.CurrentItem as TabItem;
var viewModel = BindingContext as xxxViewModel;
if(x.Header == Tab1)
{
viewModel.TabVms[0].DynamicContentView = new Page1();
}
if(x.Header == Tab2)
{
viewModel.TabVms[1].DynamicContentView = new Page2();
}
}
Any help is appreciated!
You could use DataTemplateSelector.
Creating a DataTemplateSelector:
class DymaicDataTemplateSelector : DataTemplateSelector
{
public DataTemplate Tab1Template { get; set; }
public DataTemplate Tab2Template { get; set; }
protected override DataTemplate OnSelectTemplate(object item, BindableObject container)
{
return ((TabViewModel)item).Header == "Tab1" ? Tab1Template : Tab2Template;
}
}
Consuming a DataTemplateSelector in XAML:
<ContentPage.Resources>
<ResourceDictionary>
<DataTemplate x:Key="tab1Template" x:DataType="local:TabViewModel">
<Grid Margin="10">
<Grid.RowDefinitions>
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Label
Grid.Row="0"
Margin="10"
LineBreakMode="WordWrap"
Text="{Binding Content}"
TextColor="Red"
VerticalTextAlignment="Center" />
</Grid>
</DataTemplate>
<DataTemplate x:Key="tab2Template" x:DataType="local:TabViewModel">
<Grid Margin="10">
<Grid.RowDefinitions>
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Label
Grid.Row="0"
Margin="10"
LineBreakMode="WordWrap"
Text="{Binding Content}"
TextColor="Green"
VerticalTextAlignment="Center" />
</Grid>
</DataTemplate>
<local:DymaicDataTemplateSelector
x:Key="dymaicDataTemplateSelector"
Tab1Template="{StaticResource tab1Template}"
Tab2Template="{StaticResource tab2Template}" />
</ResourceDictionary>
</ContentPage.Resources>
Assign it to the ItemTemplate property:
<CarouselView
Grid.Row="2"
CurrentItem="{Binding CurrentTabVm, Mode=TwoWay}"
CurrentItemChanged="CarouselView_CurrentItemChanged"
HorizontalScrollBarVisibility="Never"
IsScrollAnimated="True"
IsSwipeEnabled="True"
ItemTemplate="{StaticResource dymaicDataTemplateSelector}"
ItemsSource="{Binding TabVms}"
VerticalScrollBarVisibility="Never" />
An item template that includes a SkiaSharp control displaying svg, a SwipeView and some labels,
is taking forever to load when navigating to the page.
I am using StackLayout with BindableLayout.ItemSource and ItemTemplate.
Using CollectionView will let the page load much faster, but then every attempt to scroll down will slow the app for a moment, while the CollectionView generate the next batch of items.
I have moved all the code generating the items source to background, so the only thing happening on the ui thread is the binding to the ObservableCollection from the viewmodel, and drawing it.
I have also tried reducing the layouts in the item template, but it did not improve loading speed.
Xaml for page:
<DataTemplate x:Key="DataTemplateReportsItemAction">
<StackLayout Orientation="Horizontal">
<effectsView:SfEffectsView Style="{StaticResource StyleRippleEffectReportAction}">
<effectsView:SfEffectsView.GestureRecognizers>
<TapGestureRecognizer Command="{Binding ActionCommand}" />
</effectsView:SfEffectsView.GestureRecognizers>
<image:SVGImage ImageSource="{Binding IconName}"
Style="{StaticResource StyleSVGImageReportRowAction}" />
</effectsView:SfEffectsView>
<BoxView Style="{StaticResource StyleBoxViewReportItemAction}"
IsVisible="{Binding IsLast, Converter={StaticResource BoolToReverseBoolConverter}}" />
</StackLayout>
</DataTemplate>
<ControlTemplate x:Key="DataTemplateReportsItemCellDefault">
<StackLayout Orientation="Horizontal"
HorizontalOptions="FillAndExpand"
BindingContext="{TemplateBinding BindingContext}">
<StackLayout Orientation="Vertical"
HorizontalOptions="FillAndExpand"
VerticalOptions="Center">
<Label Style="{StaticResource StyleLabelReportCellTop}"
Text="{Binding DisplayValue}"
TextColor="{Binding ColorName, TargetNullValue={StaticResource ColorLabelReportCell}, FallbackValue={StaticResource ColorLabelReportCell}}" />
<Label Style="{StaticResource StyleLabelReportCellBottom}"
Text="{Binding DisplayTitle}"
TextColor="{Binding ColorName, TargetNullValue={StaticResource ColorLabelReportCell}, FallbackValue={StaticResource ColorLabelReportCell}}" />
</StackLayout>
<BoxView Style="{StaticResource StyleBoxViewReportItemCell}"
IsVisible="{Binding IsLast, Converter={StaticResource BoolToReverseBoolConverter}}" />
</StackLayout>
</ControlTemplate>
<ControlTemplate x:Key="DataTemplateReportsItemCellTrend">
<StackLayout Orientation="Horizontal"
HorizontalOptions="FillAndExpand"
BindingContext="{TemplateBinding BindingContext}">
<StackLayout Orientation="Vertical"
HorizontalOptions="FillAndExpand"
VerticalOptions="Center">
<image:SVGImage ImageSource="{Binding IconName}"
HorizontalOptions="Center" />
<Label Style="{StaticResource StyleLabelReportCellTrend}"
Text="{Binding DisplayTitle}"
TextColor="{Binding ColorName, TargetNullValue={StaticResource ColorLabelReportCell}, FallbackValue={StaticResource ColorLabelReportCell}}" />
</StackLayout>
<BoxView Style="{StaticResource StyleBoxViewReportItemCell}"
IsVisible="{Binding IsLast, Converter={StaticResource BoolToReverseBoolConverter}}" />
</StackLayout>
</ControlTemplate>
<converters:ValueToValueConverter x:Key="CellTemplateSelector"
DefaultValue="{StaticResource DataTemplateReportsItemCellDefault}">
<converters:ValueToValueList>
<converters:ValueToValueItem OnValue="{x:Static reportenums:MobileColumnMetaType.Trend}"
ToValue="{StaticResource DataTemplateReportsItemCellTrend}" />
</converters:ValueToValueList>
</converters:ValueToValueConverter>
<DataTemplate x:Key="DataTemplateReportsItemCell">
<ContentView ControlTemplate="{Binding MobileMetaType, Converter={StaticResource CellTemplateSelector}}"
HorizontalOptions="FillAndExpand" />
</DataTemplate>
<DataTemplate x:Key="DataTemplateReportsItem">
<Grid HeightRequest="{StaticResource DoubleReportRowTotalHeight}">
<Grid.RowDefinitions>
<RowDefinition Height="{StaticResource DoubleReportRowTitleHeight}" />
<RowDefinition Height="{StaticResource DoubleReportRowSwipeHeight}" />
</Grid.RowDefinitions>
<StackLayout Margin="0,5"
Orientation="Horizontal"
HorizontalOptions="FillAndExpand"
Spacing="10">
<image:SVGImage ImageSource="{Binding LactationIcon}"
IsVisible="{Binding LactationIcon, Converter={StaticResource StringToIsVisibleConverter}}"
Style="{StaticResource StyleSVGImageReportRowLactation}" />
<Label Style="{StaticResource StyleLabelReportRowTitle}"
FontSize="{Binding UseSmallTitle, Converter={StaticResource RowFontSizeConverter}}"
Text="{Binding DisplayTitle}" />
<Label Style="{StaticResource StyleLabelReportRowTitleGroup}"
IsVisible="{Binding GroupName, Converter={StaticResource StringToIsVisibleConverter}}"
Text="{Binding GroupName}" />
<Frame Style="{StaticResource StyleFrameReportRowBadge}"
BackgroundColor="{Binding Badge.BadgeType, Converter={StaticResource BadgeColorConverter}}"
IsVisible="{Binding Badge.HasBadge}">
<Label Style="{StaticResource StyleLabelReportRowTitleBadge}"
Text="{Binding Badge.BadgeTitle}" />
</Frame>
</StackLayout>
<Grid Grid.Row="1">
<SwipeView BackgroundColor="{StaticResource ColorReportViewRowBackground}"
IsEnabled="{Binding IsEditable}"
x:Name="swipey">
<SwipeView.RightItems>
<SwipeItems Mode="Reveal"
SwipeBehaviorOnInvoked="RemainOpen">
<SwipeItemView WidthRequest="{Binding Width, Source={Reference swipey}}">
<Grid BackgroundColor="{StaticResource ColorLabelReportRowActionsBackground}">
<Grid Margin="20,0">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<effectsView:SfEffectsView Style="{StaticResource StyleRippleEffectReportRowClose}"
helpers:VisualTreeHelper.ReferenceObject="{Binding Source={Reference swipey}}">
<effectsView:SfEffectsView.GestureRecognizers>
<TapGestureRecognizer Tapped="OnGroupRowCloseTapped" />
</effectsView:SfEffectsView.GestureRecognizers>
<image:SVGImage Style="{StaticResource StyleSVGImageReportRowActionsClose}" />
</effectsView:SfEffectsView>
<StackLayout Grid.Column="2"
Orientation="Horizontal"
BindableLayout.ItemTemplate="{StaticResource DataTemplateReportsItemAction}"
BindableLayout.ItemsSource="{Binding ActionItems}" />
</Grid>
</Grid>
</SwipeItemView>
</SwipeItems>
</SwipeView.RightItems>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<StackLayout Orientation="Horizontal"
HorizontalOptions="FillAndExpand"
BackgroundColor="{StaticResource ColorTransparent}"
BindableLayout.ItemTemplate="{StaticResource DataTemplateReportsItemCell}"
BindableLayout.ItemsSource="{Binding Cells}">
<StackLayout.GestureRecognizers>
<TapGestureRecognizer Command="{Binding BindingContext.NavigateCommand, Source={RelativeSource Mode=FindAncestor, AncestorType={x:Type views:BasePage}}}"
CommandParameter="{Binding}" />
</StackLayout.GestureRecognizers>
</StackLayout>
<Frame Grid.Column="1"
Padding="0"
BackgroundColor="{StaticResource ColorReportGroupRowActionsBackground}"
IsVisible="{Binding IsEditable}">
<image:SVGImage Style="{StaticResource StyleSVGImageSwipe}" />
</Frame>
</Grid>
</SwipeView>
<Grid BackgroundColor="{StaticResource ColorTransparent}"
IsVisible="{Binding IsEditable, Converter={StaticResource BoolToReverseBoolConverter}}">
<Grid.GestureRecognizers>
<TapGestureRecognizer Command="{Binding BindingContext.NavigateCommand, Source={RelativeSource Mode=FindAncestor, AncestorType={x:Type views:BasePage}}}"
CommandParameter="{Binding}" />
</Grid.GestureRecognizers>
</Grid>
</Grid>
</Grid>
</DataTemplate>
</ContentView.Resources>
<ContentView.Content>
<Grid>
<gradient:SfGradientView BackgroundBrush="{StaticResource BrushViewBackgroundGradient}" />
<Grid BackgroundColor="{StaticResource ColorReportsBrowserViewBackground}"
Margin="10,0">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<reports:ReportToolbarView />
<RefreshView Grid.Row="1"
IsRefreshing="{Binding IsRefreshing, Mode=TwoWay}"
Command="{Binding RefreshCommand}"
BackgroundColor="{StaticResource ColorReportsViewBackground}"
Margin="10,0">
<ScrollView HorizontalScrollBarVisibility="Never"
VerticalScrollBarVisibility="Default">
<StackLayout Orientation="Vertical">
<StackLayout BindableLayout.ItemsSource="{Binding ReportItems}"
BindableLayout.ItemTemplate="{StaticResource DataTemplateReportsItem}"
Orientation="Vertical" />
<BoxView HeightRequest="50" />
</StackLayout>
</ScrollView>
</RefreshView>
<sortfilter:SortFilterView Grid.Row="1"
VerticalOptions="Start"
IsVisible="{Binding SortFilterModel.IsVisible}" />
</Grid>
</Grid>
</ContentView.Content>
For comparison, replacing the item template with a simple Label makes the page load extremely fast.
Is there a way to load lists of items faster in Xamarin Forms?
Too many StackLayouts. Even worse, you stacked them into each other. Don't do that.
StackLayouts need a lot of layout cycles, as they have to calculate their size based on the children you have put in. If one of those children is a StackLayout as well, that will more than double the layout passes necessary to get to the final result.
And now guess what happens, when you have 50 or more items in your list. Those layout passes will have to run for each single item in your list.
My advice based on my experience would be to replace the StackLayouts with a grid and place your elements using their Grid.Row, Grid.Colum, Grid.RowSpan and Grid.Columnspan properties. Also set your grid sizes to either fixed values or use star based sizes. Don't use "Auto" as this needs more layout passes as well.
I am working on Xamarin forms Where i need to display grid. I am using StackLayout to create form. Everything is working until I add Grid inside StackLayout ., then I am getting error that Timeout exceeded getting exception details
Here is my code :
<ContentPage.Content>
<StackLayout VerticalOptions="StartAndExpand" BackgroundColor="White">
<StackLayout Padding="20,40,20,0" HorizontalOptions="CenterAndExpand">
<Image Source="logo.png" Aspect="AspectFit" HorizontalOptions="Center"></Image>
</StackLayout>
<StackLayout Padding="15,20,15,0" VerticalOptions="Center">
<local:ImageEntry TextColor="#98a4b4"
PlaceholderColor="#98a4b4" FontFamily="ProximaNova"
Image="LoginEmailIcon"
Placeholder="Email"
HorizontalOptions="FillAndExpand"
ImageWidth="25"
ImageHeight="20"
LineColor="#98a4b4"/>
<local:ImageEntry TextColor="#98a4b4"
PlaceholderColor="#98a4b4" FontFamily="ProximaNova"
Image="LoginPasswordIcon"
Placeholder="Password"
HorizontalOptions="FillAndExpand"
ImageWidth="23"
ImageHeight="25"
LineColor="#98a4b4" IsPassword="True"/>
<Label Text=" Forgot your password?"
HorizontalOptions="StartAndExpand" FontFamily="ProximaNova"
TextColor="#bcbcbc"/>
<StackLayout Orientation="Horizontal">
<Button x:Name="ButtonSignin" BackgroundColor="#29abdf" TextColor="White" HorizontalOptions="FillAndExpand" FontFamily="ProximaNova" Text="Sign in" FontAttributes="Bold"/>
</StackLayout>
<StackLayout Orientation="Horizontal" HorizontalOptions="CenterAndExpand">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="25px" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="auto" />
<ColumnDefinition Width="auto" />
<ColumnDefinition Width="auto" />
</Grid.ColumnDefinitions>
<Image Source="loginsideicon.png" Grid.Row="0" Grid.Column="0"></Image>
<Label Text="OR" Grid.Row="0" Grid.Column="1" FontFamily="ProximaNova" TextColor="#bcbcbc"></Label>
<Image Source="loginsideicon.png" Grid.Row="0" Grid.Column="2"></Image>
</Grid>
</StackLayout>
</StackLayout>
</StackLayout>
</ContentPage.Content>
Now When I run this code I am getting exception:
Unhandled Exception:
System.FormatException: <Timeout exceeded getting exception details> occurred
But when i comment Grid code everything is working
I noticed a few issues with your xaml :
-Use a capital letter for Auto
<ColumnDefinition Width="Auto" />
-We do not use 25px with xaml
<RowDefinition Height="25" />