Xamarin Custom ViewCell - xaml

while making custom nested views i faced a problem.
i'm trying to use my custom view(ViewCell) from various pages.
and this is how i used it.
it wont raise any error if i use View for Xaml and codebehind,
but it wont display anything.
if i try ViewCell for xaml and its codebehind, i get some error.
and this is how i used it.
in mainPage xaml
<local:UploaderCell Uploader="{Binding post.uploader}"/>
this is the line causing the error, and
<?xml version="1.0" encoding="UTF-8"?>
<ContentPage
xmlns:local="clr-namespace:EodiRoad;assembly=EodiRoad"
xmlns:ic="clr-namespace:ImageCircle.Forms.Plugin.Abstractions;assembly=ImageCircle.Forms.Plugin.Abstractions"
xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="EodiRoad.SocialPage"
Title="Story">
<ContentPage.ToolbarItems>
<ToolbarItem Icon="plus.png" Order="Primary" Priority="0" Activated="OnCreatePostClicked"/>
</ContentPage.ToolbarItems>
<StackLayout>
<ListView
x:Name="socialPostsListView"
HasUnevenRows="true"
IsPullToRefreshEnabled="true"
Refreshing="Handle_Refreshing"
SeparatorVisibility="None"
ItemSelected="OnSocialPostSelected"
>
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<StackLayout Orientation="Vertical" Padding="5">
<local:UploaderCell Uploader="{Binding post.uploader}"/>
<Image
x:Name="postImage"
Source="{Binding post.image}"
Aspect="AspectFill"
MinimumHeightRequest="200"
/>
<StackLayout Orientation="Horizontal">
<Switch IsToggled="{Binding post.isLiked}"/>
<Button Text="comment"/>
<Button Text="share"/>
</StackLayout>
<StackLayout Orientation="Vertical" HorizontalOptions="StartAndExpand">
<Label Text="{Binding post.content}"/>
<Label Text="{Binding post.uploadedTime}" TextColor="Gray"/>
</StackLayout>
</StackLayout>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</StackLayout>
</ContentPage>
this is my full mainPage xaml code.
in UploderCell.xaml
<?xml version="1.0" encoding="UTF-8"?>
<ViewCell
xmlns:ic="clr-namespace:ImageCircle.Forms.Plugin.Abstractions;assembly=ImageCircle.Forms.Plugin.Abstractions"
xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="EodiRoad.UploaderCell">
<StackLayout Orientation="Horizontal" Padding="5">
<Button Clicked="Handle_Clicked" Image="{Binding Uploader.userProfile.userThumbnail}" BorderRadius="5" HeightRequest="50" WidthRequest="50"/>
<ic:CircleImage
x:Name="userProfileImage"
HeightRequest="50"
WidthRequest="50"
Aspect="AspectFill"
Source="{Binding Uploader.userProfile.userThumbnail}"
/>
<Label Text="{Binding Uploader.username}"/>
</StackLayout>
</ViewCell>
and the codeBehind
public partial class UploaderCell : ViewCell
{
public static readonly BindableProperty UploaderProperty =
BindableProperty.Create(
propertyName: "Uploader",
returnType: typeof(UserModel),
declaringType: typeof(UploaderCell)
);
public UserModel Uploader
{
get
{ return GetValue(UploaderProperty) as UserModel; }
set
{ SetValue(UploaderProperty, value); }
}
public UploaderCell()
{
InitializeComponent();
BindingContext = this;
}
}
and i get this error from mainPage
object of type Project.UploaderCell cannot be converted to type 'xamarin.forms.view'
what am i doing wrong here?
how could i possibly fi this..

Related

Xamarin.Forms - Custom size modal

I'm new to Xamarin.Forms and I'm showing a page as a modal by using:
await Navigator.PushModalAsync(modalPage);
Modal.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="SandboxApp.Modal"
xmlns:ios="clr-namespace:Xamarin.Forms.PlatformConfiguration.iOSSpecific;assembly=Xamarin.Forms.Core"
ios:Page.ModalPresentationStyle="FullScreen">
<ContentPage.Content>
<StackLayout HorizontalOptions="Center" VerticalOptions="Center">
<Label Text="This will have some data"></Label>
<Button x:Name="closeModal" Text="Close modal" VerticalOptions="Start" HorizontalOptions="FillAndExpand" />
</StackLayout>
</ContentPage.Content>
</ContentPage>
I understand you can set the modal size to things like:
FormSheet
FullScreen
OverFullScreen
etc
But is it possible to set the size of a modal page to a custom size?
Ideally, I'd like it to be almost full screen but with a bit of a gap around the modal so you can still see the page underneath if that makes sense?
Maybe a solution to make it work. BackgroundColor="Transparent" and work with a Frame in a Grid with a Margin
In this example i use a ListView , the Gif at the bottom to show how it looks is a bit small but you see what it looks like.
MainPage.xaml
<ContentPage.Padding>
<OnPlatform x:TypeArguments="Thickness">
<On Platform="iOS" Value="0,40,0,0" />
</OnPlatform>
</ContentPage.Padding>
<ContentPage.Content>
<StackLayout>
<ListView x:Name="listView" ItemSelected="OnItemSelected" />
</StackLayout>
</ContentPage.Content>
MainPage.xaml.cs
async void OnItemSelected(object sender, SelectedItemChangedEventArgs e)
{
if (listView.SelectedItem != null)
{
var detailPage = new Page1();
detailPage.BindingContext = e.SelectedItem as Contact;
listView.SelectedItem = null;
await Navigation.PushModalAsync(detailPage);
}
}
In Page1.xaml BackgroundColor="Transparent" and a Margin in the Grid
<ContentPage
x:Class="ModalStackO.Page1"
xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
BackgroundColor="Transparent">
<ContentPage.Content>
<Grid Margin="5,20,0,0">
<Frame BackgroundColor="#1975ce" CornerRadius="15" BorderColor="Black" />
<Frame
Margin="0,35,0,0"
BackgroundColor="White"
BorderColor="Black"
CornerRadius="5"
HeightRequest="450"
WidthRequest="280">
<StackLayout
BackgroundColor="White"
HeightRequest="350"
HorizontalOptions="Center"
VerticalOptions="Center"
WidthRequest="280">
<StackLayout Orientation="Horizontal">
<Label
FontSize="Medium"
HorizontalOptions="FillAndExpand"
Text="Name:" />
<Label
FontAttributes="Bold"
FontSize="Medium"
Text="{Binding Name}" />
</StackLayout>
<StackLayout Orientation="Horizontal">
<Label
FontSize="Medium"
HorizontalOptions="FillAndExpand"
Text="Age:" />
<Label
FontAttributes="Bold"
FontSize="Medium"
Text="{Binding Age}" />
</StackLayout>
<StackLayout Orientation="Horizontal">
<Label
FontSize="Medium"
HorizontalOptions="FillAndExpand"
Text="Occupation:" />
<Label
FontAttributes="Bold"
FontSize="Medium"
Text="{Binding Occupation}" />
</StackLayout>
<StackLayout Orientation="Horizontal">
<Label
FontSize="Medium"
HorizontalOptions="FillAndExpand"
Text="Country:" />
<Label
FontAttributes="Bold"
FontSize="Medium"
Text="{Binding Country}" />
</StackLayout>
<Button
x:Name="dismissButton"
Clicked="OnDismissButtonClicked"
Text="Dismiss" />
<Button Text="Next Page" Clicked="Button_Clicked" />
</StackLayout>
</Frame>
</Grid>
</ContentPage.Content>
</ContentPage>
Page1.xaml.cs
async void OnDismissButtonClicked(object sender, EventArgs args)
{
await Navigation.PopModalAsync();
}
private async void Button_Clicked(object sender, EventArgs e)
{
var detailPage = new Page2();
await Navigation.PushModalAsync(detailPage);
}
Then in Page2.xaml BackgroundColor="Transparent" and a bit more Margin in the Grid to show Page1 also
<ContentPage
x:Class="ModalStackO.Page2"
xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
BackgroundColor="Transparent">
<ContentPage.Content>
<Grid Margin="10,50,0,0">
<Frame BackgroundColor="#1975ce" CornerRadius="15" BorderColor="Black" />
<Frame
Margin="0,35,0,0"
BackgroundColor="White"
BorderColor="Black"
CornerRadius="5"
HeightRequest="450"
WidthRequest="280">
<StackLayout>
<Label
HorizontalOptions="CenterAndExpand"
Text="Welcome to Page 2"
VerticalOptions="CenterAndExpand" />
<Button Text="Back" Clicked="Button_Clicked" />
</StackLayout>
</Frame>
</Grid>
</ContentPage.Content>
Page2.xaml.cs to go back
private async void Button_Clicked(object sender, EventArgs e)
{
await Navigation.PopModalAsync();
}
https://github.com/rotorgames/Rg.Plugins.Popup
This is the plugin I always use to meet the UI look requirement you mentioned (padding - so I can still see the page underneath).
Instead recommended to use Popups
you have 3 options, and all are customizable in size and animation
Free
1: https://github.com/rotorgames/Rg.Plugins.Popup
Free
2: https://learn.microsoft.com/en-us/xamarin/community-toolkit/views/popup
Pay or Community Account for Free
3: https://help.syncfusion.com/xamarin/popup/getting-started

Can you place a CarouselView in another CarouselView?

I would like 2 ContentViews in the first CarouselView, but then I want to place another CarouselView in the second ContentView.
The code below gives me a "Value cannot be null". When I remove the ItemTemplate from the second CarouselView it builds but then I get this on the second ContentView (see image).
<CarouselView x:Name="outerCarousel">
<CarouselView.ItemsSource>
<x:Array Type="{x:Type ContentView}">
<ContentView>
<ContentView.Content>
<Frame BackgroundColor="Red" />
</ContentView.Content>
</ContentView>
<ContentView>
<ContentView.Content>
<Frame>
<CarouselView x:Name="innerCarousel" Margin="50">
<CarouselView.ItemsSource>
<x:Array Type="{x:Type ContentView}">
<ContentView>
<ContentView.Content>
<Frame BackgroundColor="Green" />
</ContentView.Content>
</ContentView>
<ContentView>
<ContentView.Content>
<Frame BackgroundColor="Blue" />
</ContentView.Content>
</ContentView>
</x:Array>
</CarouselView.ItemsSource>
<CarouselView.ItemTemplate>
<DataTemplate>
<ContentView Content="{Binding .}" />
</DataTemplate>
</CarouselView.ItemTemplate>
</CarouselView>
</Frame>
</ContentView.Content>
</ContentView>
</x:Array>
</CarouselView.ItemsSource>
<CarouselView.ItemTemplate>
<DataTemplate>
<ContentView Content="{Binding .}" />
</DataTemplate>
</CarouselView.ItemTemplate>
</CarouselView>
You could refer to the code below:
outerCarousel: Page7
Xaml:
<ContentPage.Content>
<CarouselView x:Name="outerCarousel" ItemsSource="{Binding outers}">
<CarouselView.ItemsLayout>
<LinearItemsLayout Orientation="Horizontal" />
</CarouselView.ItemsLayout>
<CarouselView.ItemTemplate>
<DataTemplate>
<ContentView Content="{Binding content}"></ContentView>
</DataTemplate>
</CarouselView.ItemTemplate>
</CarouselView>
</ContentPage.Content>
Code Behind:
public partial class Page7 : ContentPage
{
public Page7()
{
InitializeComponent();
this.BindingContext = new OuterViewModel();
}
}
public class Outer
{
public ContentView content { get; set; }
}
public class OuterViewModel
{
public ObservableCollection<Outer> outers { get; set; }
public OuterViewModel()
{
outers = new ObservableCollection<Outer>()
{
new Outer(){ content=new View1()},
new Outer(){ content=new View2()}
};
}
}
innerCarousel: View1, View2
View1:
<ContentView.Content>
<Frame BackgroundColor="Red" />
</ContentView.Content>
View2:
<ContentView.Content>
<CarouselView x:Name="innerCarousel" Margin="50">
<CarouselView.ItemsLayout>
<LinearItemsLayout Orientation="Vertical" />
</CarouselView.ItemsLayout>
<CarouselView.ItemsSource>
<x:Array Type="{x:Type ContentView}">
<ContentView>
<ContentView.Content>
<Frame BackgroundColor="Green" />
</ContentView.Content>
</ContentView>
<ContentView>
<ContentView.Content>
<Frame BackgroundColor="Blue" />
</ContentView.Content>
</ContentView>
</x:Array>
</CarouselView.ItemsSource>
<CarouselView.ItemTemplate>
<DataTemplate>
<ContentView Content="{Binding .}" />
</DataTemplate>
</CarouselView.ItemTemplate>
</CarouselView>
</ContentView.Content>

How bind a command in DataTemplate in Resource Dictionary?

I'm trying to make a better solution architecture, for that I've separated many parts of code in differents files. Because my application use a lot of DataTemplates, I push them in different ResourceDictionary.xaml files.
Problem :
I have a view Agenda.xaml, with the viewModel AgendaViewModel. This view have a ListView which call's datatemplate in external ResourceDictionary file. But if I want put a Binding Command in the dataTemplate, the command is never executed because (I guess) the resource Dictionary where is my DataTemplate not reference ViewModel.
What can I do ?
I've already tried some weird Binding code like
<TapGestureRecognizer Command="{Binding BindingContext.OpenActiviteCommand, Source={x:Reference agendaPage}}" CommandParameter="{Binding .}"/>
Where "agendaPage" is the x:Name of Agenda.xaml.
All I found on Google was about WPF and Binding property not available on Xamarin Forms (RelativeSource, ElementName etc...)
I know I can put dataTemplate in my Agenda.xaml view, but I really want keep it in an external file. I want avoid view files with 1500 lines....
This is my Agenda.xaml view
<?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="Corim.Portable.CorimTouch.ViewForms.Agenda.AgendaViewDetail"
xmlns:converters="clr-namespace:Corim.Portable.CorimTouch.Converters"
Title="Agenda"
x:Name="agendaPage">
<ContentPage.Content>
<Grid HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand" BackgroundColor="{StaticResource LightGrayCorim}">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<!-- Liste itv,pointage,activite -->
<ListView
x:Name="listAgenda"
Grid.Row="1"
SeparatorVisibility="None"
HasUnevenRows="True"
SelectionMode="None"
CachingStrategy="RecycleElement"
ItemsSource="{Binding AgendaList}"
ItemTemplate="{StaticResource agendaTemplateSelector}"
BackgroundColor="{StaticResource LightGrayCorim}">
</ListView>
</Grid>
</ContentPage.Content>
</ContentPage>
And this is one part of Datatemplate in AgendaTemplates.xaml
<DataTemplate x:Key="agenda-adresse-intervention">
<ViewCell>
<Frame Margin="10,5,10,0" HasShadow="False" Padding="0" CornerRadius="10" IsClippedToBounds="True">
<controls:CustomTappedStackLayout
BackgroundColor="White"
TappedBackgroundColor="{StaticResource RollOver}"
HorizontalOptions="FillAndExpand"
Orientation="Horizontal"
Padding="10">
<StackLayout.GestureRecognizers>
<TapGestureRecognizer Command="{Binding Path=BindingContext.OpenParcCommand, Source={x:Reference agendaPage}}" CommandParameter="{Binding .}" NumberOfTapsRequired="1"/>
</StackLayout.GestureRecognizers>
<Image
Source="localisation_adresse"
WidthRequest="30"
HeightRequest="30"
Aspect="AspectFit"
HorizontalOptions="Start"
Margin="10"
VerticalOptions="StartAndExpand"/>
<StackLayout
HorizontalOptions="FillAndExpand"
Orientation="Vertical">
<Label
Text="{Binding Client}"
IsVisible="{Binding Client, Converter={StaticResource StringEmptyBooleanConverter}}"
FontFamily="{StaticResource SemiBoldFont}"
FontSize="{StaticResource MediumTextSize}"
TextColor="Black"/>
<Label
Text="{Binding Title}"
IsVisible="{Binding Title, Converter={StaticResource StringEmptyBooleanConverter}}"
FontFamily="{StaticResource RegularFont}"
FontSize="{StaticResource DefaultTextSize}"
TextColor="Gray"/>
</StackLayout>
</controls:CustomTappedStackLayout>
</Frame>
</ViewCell>
</DataTemplate>
But if I want put a Binding Command in the dataTemplate, the command
is never executed because (I guess) the resource Dictionary where is
my DataTemplate not reference ViewModel.
You guess wrong: it's totally fine to do what you are doing and should work transparently. The binding is resolved at runtime your data template does not know anything about the object that will be bound.
1st: drop the BindingContext.OpenActiviteCommand nonsense :) Just bind to OpenActiviteCommand, the only question is:
2nd: Where is your OpenActiviteCommand ?
The data context of your AgendaTemplates is the item in your AgendaList.
If the type of the AgendaList is an ObservableCollection<AgendaViewModel>, and your AgendaViewModel has a OpenParcCommand then it should be fine:
public class AgendaViewModel
{
public AgendaViewModel(ICommand openParcCommand)
{
OpenParcCommand = openParcCommand;
}
public ICommand OpenParcCommand { get; }
}
and in your AgendaPageViewModel:
public class AgendaPageViewModel
{
public ObservableCollection<AgendaViewModel> AgendaList { get; }
}
Thanks to #Roubachof
The soluce was replace my ListView of InterventionModel by ListView of AgendaDataViewModel.
AgendaViewModel is a new class which contains all the commands I need, and an InterventionModel.
this is AgendaDataViewModel :
public class AgendaDataViewModel : HybridContentViewModel
{
private InterventionModel _model;
public InterventionModel Model
{
get => _model;
set { _model = value; }
}
public ICommand OpenActiviteCommand { get; private set; }
public AgendaDataViewModel()
{
this.OpenActiviteCommand = new Command<InterventionModel>(this.OpenActivite);
}
/// <summary>
/// Ouvre le formulaire d'édition de l'activité
/// </summary>
/// <param name="model"></param>
private void OpenActivite(InterventionModel model)
{
//TODO amener sur le formulaire d'activité
}
}
my AgendaTemplate.xaml
<!--Template pour l'affichage du parc-->
<DataTemplate x:Key="agenda-adresse-intervention">
<ViewCell>
<Frame Margin="10,5,10,0" HasShadow="False" Padding="0" CornerRadius="10" IsClippedToBounds="True">
<controls:CustomTappedStackLayout
BackgroundColor="White"
TappedBackgroundColor="{StaticResource RollOver}"
HorizontalOptions="FillAndExpand"
Orientation="Horizontal"
Padding="10">
<StackLayout.GestureRecognizers>
<TapGestureRecognizer Command="{Binding OpenParcCommand}" CommandParameter="{Binding Model}" NumberOfTapsRequired="1"/>
</StackLayout.GestureRecognizers>
<Image
Source="localisation_adresse"
WidthRequest="30"
HeightRequest="30"
Aspect="AspectFit"
HorizontalOptions="Start"
Margin="10"
VerticalOptions="StartAndExpand"/>
<StackLayout
HorizontalOptions="FillAndExpand"
Orientation="Vertical">
<Label
Text="{Binding Model.Client}"
IsVisible="{Binding Model.Client, Converter={StaticResource StringEmptyBooleanConverter}}"
FontFamily="{StaticResource SemiBoldFont}"
FontSize="{StaticResource MediumTextSize}"
TextColor="Black"/>
<Label
Text="{Binding Model.Title}"
IsVisible="{Binding Model.Title, Converter={StaticResource StringEmptyBooleanConverter}}"
FontFamily="{StaticResource RegularFont}"
FontSize="{StaticResource DefaultTextSize}"
TextColor="Gray"/>
</StackLayout>
</controls:CustomTappedStackLayout>
</Frame>
</ViewCell>
</DataTemplate>
As you can see, the values binding is made by this line :
{Binding Model.Client}
where Client is the name of Binded property. And to Bind a Command, you don't need Model, and just bind like this :
Command={Binding CommandName}
Hope it helps someone in the future !

Xamarin.iOS Error - Application windows are expected to have a root view controller .... Using Static Binding

I am getting this error:
Foundation.MonoTouchException: Objective-C exception thrown. Name:
NSInternalInconsistencyException Reason: Application windows are
expected to have a root view controller at the end of application
launch
Using Xamarin.iOS if I use inside my xaml file this kind of Binding:
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:prism="clr-namespace:Prism.Mvvm;assembly=Prism.Forms"
xmlns:converters="clr-namespace:AppAlgorix.Converters"
xmlns:resources="clr-namespace:AppAlgorix.Resources"
prism:ViewModelLocator.AutowireViewModel="True"
x:Class="AppAlgorix.Views.LoginPage">
<ContentPage.Resources>
<ResourceDictionary>
<converters:MaskedCardConverter x:Key="cvtMaskedCard"></converters:MaskedCardConverter>
</ResourceDictionary>
</ContentPage.Resources>
<ContentPage.Content>
<StackLayout Orientation="Vertical" HorizontalOptions="Center" Padding="20">
<StackLayout Orientation="Vertical" HorizontalOptions="FillAndExpand" VerticalOptions="Fill" HeightRequest="80">
<Label Text="SEJA BEM VINDO" HorizontalOptions="CenterAndExpand" FontSize="Large" FontAttributes="None" TextColor="{Binding Source={x:Static resources:AppParameters.AppLabelColorDefault}}"></Label>
</StackLayout>
</StackLayout>
</ContentPage.Content>
</ContentPage>
I have tried this format also:
<Label Text="SEJA BEM VINDO" HorizontalOptions="CenterAndExpand"
FontSize="Large" FontAttributes="None" TextColor="{Binding
AppLabelColorDefault, Source={x:Static
resources:AppParameters}}"></Label>
My Parameters Class is this:
namespace AppAlgorix.Resources
{
public static class AppParameters
{
public static string AppLabelColorDefault
{
get
{
var color = Parameters.ResourceManager.GetString("applabelcolordefault");
return color;
}
}
}
}
My Xamarin project has Android and iOS. This approach works with Android, but do not work with iOS.
If I change my view to this :
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:prism="clr-namespace:Prism.Mvvm;assembly=Prism.Forms"
xmlns:converters="clr-namespace:AppAlgorix.Converters"
prism:ViewModelLocator.AutowireViewModel="True"
x:Class="AppAlgorix.Views.LoginPage">
<ContentPage.Resources>
<ResourceDictionary>
<converters:MaskedCardConverter x:Key="cvtMaskedCard"></converters:MaskedCardConverter>
</ResourceDictionary>
</ContentPage.Resources>
<ContentPage.Content>
<StackLayout Orientation="Vertical" HorizontalOptions="Center" Padding="20">
<StackLayout Orientation="Vertical" HorizontalOptions="FillAndExpand" VerticalOptions="Fill" HeightRequest="80">
<Label Text="SEJA BEM VINDO" HorizontalOptions="CenterAndExpand" FontSize="Large" FontAttributes="None" TextColor="Black"></Label>
</StackLayout>
</StackLayout>
</ContentPage.Content>
</ContentPage>
I can execute and see my view in emulator...
So, I think my problem is this Binding format...
My question is... How to resolve this error in Xamarin.iOS, without breaking Xamarin.Android ?

Xamarin Forms - My ContentPresenter won't show its Content

I'm still getting used to Xamarin Forms, so I have the following control called PopupFrame:
PopupFrame.cs
[XamlCompilation(XamlCompilationOptions.Compile)]
public partial class PopupFrame : ContentView
{
public static readonly BindableProperty PopupContentProperty =
BindableProperty.Create(nameof(PopupContent), typeof(View), typeof(PopupFrame));
public View PopupContent
{
get { return (View)GetValue(PopupContentProperty); }
set { SetValue(PopupContentProperty, value); }
}
public PopupFrame()
{
InitializeComponent();
}
}
PopupFrame.xaml
<?xml version="1.0" encoding="UTF-8"?>
<ContentView xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="TestApp.Core.Controls.PopupFrame">
<Frame>
<StackLayout>
<Label Text="--- TEST TITLE ---" />
<ContentPresenter Content="{TemplateBinding PopupContent}" />
</StackLayout>
</Frame>
</ContentView>
In my view:
<popCtl:PopupFrame HorizontalOptions="Center"
VerticalOptions="Center">
<popCtl:PopupFrame.PopupContent>
<ListView x:Name="ListUsers">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<ViewCell.View>
<Label Text="{Binding Name}"
HorizontalOptions="CenterAndExpand"
VerticalOptions="Center" />
</ViewCell.View>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</popCtl:PopupFrame.PopupContent>
</popCtl:PopupFrame>
So what's happening is that When the ContentView control shows, only the Label (with the text -- TEST TITLE -- is displayed, but not the ListView).
I've also tried replacing the ContentPreseter with a ContentView, but same result: my ListView doesn't not show. And I made sure that data does in fact exist in the ItemsSource of the ListView (set in code-behind).
Is my ContentView setup wrong??
TemplateBinding can only be used to bind from inside a control-template. In order for your binding to work - you can use ReferenceExtension to refer to parent control.
For ex, update your binding as following:
<ContentView xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="TestApp.Core.Controls.PopupFrame"
x:Name="_parent">
<Frame>
<StackLayout>
<Label Text="--- TEST TITLE ---" />
<ContentPresenter
Content="{Binding Path=PopupContent, Source={x:Reference _parent}}" />
</StackLayout>
</Frame>
</ContentView>