I am using Xamarin.Forms and I have 2 pages, one is a List View, the other is a just a view I am using as a filter for the List View. I am currently using Navigation.PushAsync to display this page, my question is, is there away to present it like a side menu? I know there is Master Detail View which I am already using for the main menu and I dont think I can have 2 Master Details in my app, I tried that approach but it adds an additional navigation.
Here is my code.
public partial class PatientsPage : ContentPage
{
public PatientsPage()
{
InitializeComponent();
ToolbarItems.Add(new ToolbarItem("Filter", "filter.png", () => { openFilter(); }));
}
public async void openFilter()
{
await Navigation.PushAsync(new PatientFiltersPage());
}
}
UPDATE
Is there away to have 2 details in 1 master to accomplish this? I really don't want to use a 3rd party library.
I personally do not know of
any way to have 2 details in 1 master
According to the documentation:
The Xamarin.Forms MasterDetailPage is a page that manages two related pages of information – a master page that presents items, and a detail page that presents details about items on the master page.
So in theory only one Detail page is allowed per Master page (although the detail page can be a NavigationPage itself).
But if you are flexible about how to approach your problem, i would suggest using an overlay with AbsoluteLayout.
As an example, look at the image below, where i have a view over the main CollectionView that can be shown or hidden by tapping on the "Filter" button:
Of course you can get as creative as you want, and make the view appear sliding from below, or from the side, or fading in: there is a robust support for animations in Xamarin.Forms. Also the view can be scrollable so that if you have a variety of filters you do not cover the whole CollectionView with the Filter.
If that kind of solution is tolerable, you can achieve it as follows:
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="FilterDetail.StartPage">
<ContentPage.ToolbarItems>
<ToolbarItem Text="Filter"
Clicked="ToolbarItem_Clicked"/>
</ContentPage.ToolbarItems>
<ContentPage.Content>
<AbsoluteLayout>
<CollectionView x:Name="listView" AbsoluteLayout.LayoutBounds="0,0,1,1"
AbsoluteLayout.LayoutFlags="All">
<CollectionView.ItemTemplate>
<DataTemplate>
<StackLayout>
<Frame Margin="15">
<Label Text="{Binding .}"/>
</Frame>
</StackLayout>
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
<ContentView x:Name="FilterOverlay"
IsVisible="True" VerticalOptions="End"
AbsoluteLayout.LayoutBounds="0,0,1,1"
AbsoluteLayout.LayoutFlags="All"
BackgroundColor="Transparent">
<Frame CornerRadius="10"
Margin="10"
HorizontalOptions="FillAndExpand" InputTransparent="False">
<StackLayout Padding="0">
<Label x:Name="FilterText"
Text="Filter Options"
FontSize="Medium"
TextColor="Black"/>
<StackLayout Orientation="Horizontal"
HorizontalOptions="CenterAndExpand">
<Label Text="Filter key 1"/>
<Switch IsToggled="True" />
</StackLayout>
<StackLayout Orientation="Horizontal"
HorizontalOptions="CenterAndExpand">
<Label Text="Filter key 2"/>
<Switch IsToggled="True" />
</StackLayout>
<StackLayout Orientation="Horizontal"
HorizontalOptions="CenterAndExpand">
<Label Text="Filter key 3"/>
<Switch IsToggled="False" />
</StackLayout>
<StackLayout Orientation="Horizontal"
HorizontalOptions="CenterAndExpand">
<Label Text="Filter key 4"/>
<Switch IsToggled="True" />
</StackLayout>
<Button Text="Apply"
HeightRequest="30"
Padding="0"
BackgroundColor="Accent"/>
</StackLayout>
</Frame>
</ContentView>
</AbsoluteLayout>
</ContentPage.Content>
</ContentPage>
Code behind
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Xamarin.Forms;
using Xamarin.Forms.Xaml;
namespace FilterDetail
{
[XamlCompilation(XamlCompilationOptions.Compile)]
public partial class StartPage : ContentPage
{
public StartPage()
{
InitializeComponent();
var items = new List<String>();
for (int i = 0; i < 1000; i++)
items.Add($"Item {i}");
listView.SetBinding(CollectionView.ItemsSourceProperty, new Binding() { Source = items, Path = "." });
}
private void ToolbarItem_Clicked(object sender, EventArgs e)
{
FilterOverlay.IsVisible = !FilterOverlay.IsVisible;
}
}
}
Update
In order to simulate a second Master/Menu we can simply modify our solution presented above in order to expand our overlay vertically and add some animation so that instead of simply appear and disappear, the overlay hides to the right.
Let's see how this is done:
The Overlay
Add an overlay that covers the whole screen except from a margin on the left so that it looks like a Master Menu.
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="FilterDetail.StartPage">
<ContentPage.ToolbarItems>
<ToolbarItem Text="Filter"
Clicked="ToolbarItem_Clicked"/>
</ContentPage.ToolbarItems>
<ContentPage.Content>
<AbsoluteLayout>
<CollectionView x:Name="listView" AbsoluteLayout.LayoutBounds="0,0,1,1"
AbsoluteLayout.LayoutFlags="All">
<CollectionView.ItemTemplate>
<DataTemplate>
<StackLayout>
<Frame Margin="15">
<Label Text="{Binding .}"/>
</Frame>
</StackLayout>
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
<ContentView x:Name="FilterOverlay"
IsVisible="True"
AbsoluteLayout.LayoutBounds="0,0,1,1"
AbsoluteLayout.LayoutFlags="All"
BackgroundColor="Transparent">
<Frame CornerRadius="10"
Margin="100,10,0,10"
HorizontalOptions="FillAndExpand"
VerticalOptions="FillAndExpand"
InputTransparent="False">
<StackLayout Padding="0">
<Label x:Name="FilterText"
Text="Filter Options"
FontSize="Medium"
TextColor="Black"/>
<StackLayout Orientation="Horizontal"
HorizontalOptions="CenterAndExpand">
<Label Text="Filter key 1"/>
<Switch IsToggled="True" />
</StackLayout>
<StackLayout Orientation="Horizontal"
HorizontalOptions="CenterAndExpand">
<Label Text="Filter key 2"/>
<Switch IsToggled="True" />
</StackLayout>
<StackLayout Orientation="Horizontal"
HorizontalOptions="CenterAndExpand">
<Label Text="Filter key 3"/>
<Switch IsToggled="False" />
</StackLayout>
<StackLayout Orientation="Horizontal"
HorizontalOptions="CenterAndExpand">
<Label Text="Filter key 4"/>
<Switch IsToggled="True" />
</StackLayout>
<Button Text="Apply"
HeightRequest="30"
Padding="0"
BackgroundColor="Accent"
VerticalOptions="EndAndExpand"/>
</StackLayout>
</Frame>
</ContentView>
</AbsoluteLayout>
</ContentPage.Content>
</ContentPage>
Next, add some animation to ToolbarItem_Clicked so that on tapping the Filter toolbar item, the overlay
hides to the right
Code Behind:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Xamarin.Forms;
using Xamarin.Forms.Xaml;
namespace FilterDetail
{
[XamlCompilation(XamlCompilationOptions.Compile)]
public partial class StartPage : ContentPage
{
public StartPage()
{
InitializeComponent();
var items = new List<String>();
for (int i = 0; i < 1000; i++)
items.Add($"Item {i}");
listView.SetBinding(CollectionView.ItemsSourceProperty, new Binding() { Source = items, Path = "." });
}
private async void ToolbarItem_Clicked(object sender, EventArgs e)
{
if (FilterOverlay.IsVisible)
{
// If overlay is visible, slide it to the right, and set as invisible.
await FilterOverlay.TranslateTo(this.Width-100, FilterOverlay.Y);
FilterOverlay.IsVisible = false;
}
else
{
// If overlay is invisible, make it visible and slide to the left.
FilterOverlay.IsVisible = true;
await FilterOverlay.TranslateTo(0, FilterOverlay.Y);
}
}
}
}
And that's it. The result looks like this:
Of course this is only a sample, and a bit of extra work on the overlay and on the animation can give you amazing results. Enjoy!
Related
I'm trying to create my first Xamarin forms app. This is my first app using C#, And my first Xamarin app, so I ran with the template that gives me the "burger menu" when I created the project in Visual Studio 2019. I found quick guide on youtube that used Rg.Plugins to invoke the popup. I tried doing the same, And I can see it does work, sort of, since the pop-up page is being rendered using a fade in animation. As soon as it has been rendered, it disapears, And the underlying page is being "grayed out", so it seems like it's active, but I simply can't see it.
My guess is that it has something to do with how my other elements is being drawn or because I used the burger menu template? If anyone have an idea about what's going on, I would be glad :)
I have been using the iOS Simulator to test out the app.
Heres XAML for the page invoking the pop-up:
"Frontpage" that invokes on "Clicked="PopupCPR_clicked":
<?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="EWSMonitor.Views.Monitorering"
xmlns:vm="clr-namespace:EWSMonitor.ViewModels"
Title="{Binding Title}">
<ContentPage.BindingContext>
<vm:MonitoreringModel />
</ContentPage.BindingContext>
<ContentPage.Resources>
<ResourceDictionary>
<Color x:Key="Accent">#2a2b2b</Color>
</ResourceDictionary>
</ContentPage.Resources>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<BoxView Color="{StaticResource Primary}" Grid.Column="0" Grid.RowSpan="2"/>
<StackLayout BackgroundColor="{StaticResource Primary}" VerticalOptions="FillAndExpand" HorizontalOptions="Fill">
<StackLayout Orientation="Horizontal" HorizontalOptions="Center" VerticalOptions="Center">
<ContentView Padding="0,40,0,40" VerticalOptions="FillAndExpand">
<Image Source="logo.png" VerticalOptions="Center" HeightRequest="100" />
</ContentView>
</StackLayout>
</StackLayout>
<ScrollView Grid.Row="1">
<StackLayout Orientation="Vertical" Padding="30,24,30,24" Spacing="10" WidthRequest="200">
<Label TextColor="{StaticResource Sekundær}" Text="Indtast patient ID (CPR) eller klik på "Monitorer uden patient identifikation"." FontSize="20"/>
<Label TextColor="{StaticResource Sekundær}" Text="Du kan vælge at scanne patientens armbånd eller indtast CPR nummer manuelt! Benyt altid en scanner hvor det er muligt!" FontSize="16" Padding="0,0,0,0"/>
<Label TextColor="{StaticResource Sekundær}" FontSize="12" Padding="0,24,0,0">
<Label.FormattedText>
<FormattedString>
<FormattedString.Spans>
<Span Text="Fremsøg patient: "/>
<!-- <Span Text="https://aka.ms/xamarin-quickstart" FontAttributes="Bold"/> -->
</FormattedString.Spans>
</FormattedString>
</Label.FormattedText>
</Label>
<Grid VerticalOptions="FillAndExpand" HorizontalOptions="FillAndExpand">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"></RowDefinition>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"></ColumnDefinition>
<ColumnDefinition Width="*"></ColumnDefinition>
</Grid.ColumnDefinitions>
<!--Command="{Binding OpenWebCommand}"-->
<Button Margin="1,1,1,1" x:Name="PopupCPR" Text="Indtast CPR"
Clicked="PopupCPR_clicked"
BackgroundColor="{StaticResource Sekundær}"
TextColor="{StaticResource Primary}"
CornerRadius="5" WidthRequest="150" HeightRequest="30" Grid.Row="0" Grid.Column="0" />
<Button Margin="1,1,1,1" Text="Monitorer uden patientidentifikation"
Command="{Binding OpenWebCommand}"
BackgroundColor="{StaticResource Sekundær}"
TextColor="{StaticResource Primary}"
CornerRadius="5" WidthRequest="150" HeightRequest="30" Grid.Row="0" Grid.Column="1" />
</Grid>
</StackLayout>
</ScrollView>
</Grid>
</ContentPage>
The xaml.cs file:
using Rg.Plugins.Popup.Services;
using System;
using System.ComponentModel;
using Xamarin.Forms;
using Xamarin.Forms.Xaml;
namespace EWSMonitor.Views
{
public partial class Monitorering : ContentPage
{
public Monitorering()
{
InitializeComponent();
}
private PopupCPR _PopupCPR;
private async void PopupCPR_clicked(object sender, EventArgs e)
{
_PopupCPR = new PopupCPR();
await PopupNavigation.Instance.PushAsync(_PopupCPR);
}
}
}
Then the popup page xaml:
<?xml version="1.0" encoding="utf-8" ?>
<pages:PopupPage
xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:pages="clr-namespace:Rg.Plugins.Popup.Pages;assembly=Rg.Plugins.Popup"
xmlns:animations="clr-namespace:Rg.Plugins.Popup.Animations;assembly=Rg.Plugins.Popup"
x:Class="EWSMonitor.Views.PopupCPR"
xmlns:vm="clr-namespace:EWSMonitor.ViewModels"
Title="{Binding Title}">
<pages:PopupPage.Animation>
<animations:ScaleAnimation
PositionIn="Center"
PositionOut="Center"
ScaleIn="1.2"
ScaleOut="0.8"
DurationIn="400"
DurationOut="300"
EasingIn="SinOut"
EasingOut="SinIn"
HasBackgroundAnimation="True"/>
</pages:PopupPage.Animation>
<StackLayout VerticalOptions="Center" HorizontalOptions="FillAndExpand" Padding="20, 20, 20, 20">
<StackLayout BackgroundColor="{StaticResource Sekundær}" Padding="0, 10, 0, 0">
<Label Text="Dette er et fedt pop-up vindue" TextColor="{StaticResource Primary}" FontSize="20" HorizontalOptions="Center"></Label>
<ScrollView>
<StackLayout>
<StackLayout Orientation="Horizontal">
<Entry Placeholder="Test Entry"
HorizontalOptions="FillAndExpand"
BindingContext="{x:Reference Switch}"
IsEnabled="{Binding Path=IsToggled}"
PlaceholderColor="Silver"
Keyboard="Email"
TextColor="Gray"></Entry>
<Switch IsToggled="True" x:Name="Switch"></Switch>
</StackLayout>
<ActivityIndicator Color="Gray" IsRunning="True"></ActivityIndicator>
<Slider Value="0.4" x:Name="Slider"></Slider>
<ProgressBar BindingContext="{x:Reference Slider}" Progress="{Binding Path=Value}"></ProgressBar>
<Button Text="Close" TextColor="{StaticResource Sekundær}" Clicked="OnClose"></Button>
</StackLayout>
</ScrollView>
</StackLayout>
</StackLayout>
<!-- <ContentView x:Name="popupCPRVindue" BackgroundColor="{StaticResource Sekundær}" Padding="10,0" IsVisible="true" AbsoluteLayout.LayoutBounds="0, 0, 1, 1">
<StackLayout VerticalOptions="Center" HorizontalOptions="Center">
<Label Text="Hejsa" />
<Button Text="Luk" TextColor="{StaticResource Sekundær}" Clicked="OnClose"></Button>
</StackLayout>
</ContentView>
-->
<!--
<StackLayout
VerticalOptions="Center"
HorizontalOptions="Center"
Padding="20, 20, 20, 20">
<Label
Text="Dette er en stor fed TEST" TextColor="{StaticResource Sekundær}"/>
<Button Text="Luk" TextColor="{StaticResource Sekundær}" Clicked="OnClose"></Button>
</StackLayout>
-->
</pages:PopupPage>
And the xaml.cs for the popup page:
using Rg.Plugins.Popup.Pages;
using Rg.Plugins.Popup.Services;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Xamarin.Forms;
using Xamarin.Forms.Xaml;
namespace EWSMonitor.Views
{
[XamlCompilation(XamlCompilationOptions.Compile)]
public partial class PopupCPR : PopupPage
{
public PopupCPR()
{
InitializeComponent();
}
private async void OnClose(object sender, EventArgs e)
{
await PopupNavigation.Instance.PopAsync();
}
protected override Task OnAppearingAnimationEndAsync()
{
return Content.FadeTo(0, 5);
}
protected override Task OnAppearingAnimationBeginAsync()
{
return Content.FadeTo(1);
}
}
}
Here is a picture where it possible to see it fade in, before it just disappears:
Popup before it dissapears
you are explicitly setting the Opacity to 0
Content.FadeTo(0, 5);
I am having issues binding the values of a string[] to the DataTemplate of a BindableLayout. I have recreated the issue in the AboutPage of the Shell Flyout Template.
AboutPage.xaml
<ContentPage.BindingContext>
<vm:AboutViewModel />
</ContentPage.BindingContext>
<StackLayout VerticalOptions="Center"
Padding="20"
BindableLayout.ItemsSource="{Binding Data}">
<BindableLayout.ItemTemplate>
<DataTemplate>
<Label FontSize="Large"
Text="{Binding .}"
BackgroundColor="PowderBlue"/>
</DataTemplate>
</BindableLayout.ItemTemplate>
</StackLayout>
AboutViewModel.cs
namespace App2.ViewModels
{
public class AboutViewModel : BaseViewModel
{
private string[] _data;
public string[] Data
{
get
{
return _data;
}
set
{
if (_data != value)
{
_data = value;
OnPropertyChanged();
}
}
}
public AboutViewModel()
{
Title = "About";
Data = new string[] { "One", "Two", "Three" };
}
}
}
When the page first opens, the the correct number of labels are there but without any text.
If I edit the Text="{Binding .}" the binding works after Xaml Hot Reload.
Why on earth are the strings not being displayed in the first place when they're clearly not empty or null?
I have solved this problem in an unexpected way. Simply by moving the DataTemplate into its own file, this problem goes away. Can someone please explain to me why this works? My new code produces two StackLayouts side by side, bound to the same data but only the Stackview on the right, with its DataTemplate defined elsewhere as ListItemView.xaml shows the data when the app is run. The StackView on the left has empty Labels at first, then after I delete the full-stop (.) from Text="{Binding .}" and replace it, Xaml Hot Reload runs and the strings are displayed.
ListItemView.xaml
<DataTemplate xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="App2.Views.ListItemView">
<Label FontSize="Large"
Text="{Binding ., Mode=OneWay}"
BackgroundColor="PowderBlue"/>
</DataTemplate>
AboutPage.xaml
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="App2.Views.AboutPage"
xmlns:vm="clr-namespace:App2.ViewModels"
xmlns:views="clr-namespace:App2.Views"
Title="{Binding Title}"
x:DataType="vm:AboutViewModel">
<ContentPage.BindingContext>
<vm:AboutViewModel />
</ContentPage.BindingContext>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="1*"/>
<ColumnDefinition Width="1*"/>
</Grid.ColumnDefinitions>
<StackLayout VerticalOptions="Center"
Padding="20"
BindableLayout.ItemsSource="{Binding Data}"
Grid.Column="0">
<BindableLayout.ItemTemplate>
<DataTemplate>
<Label FontSize="Large"
Text="{Binding ., Mode=OneWay}"
BackgroundColor="PowderBlue"/>
</DataTemplate>
</BindableLayout.ItemTemplate>
</StackLayout>
<StackLayout VerticalOptions="Center"
Padding="20"
BindableLayout.ItemsSource="{Binding Data}"
Grid.Column="1">
<BindableLayout.ItemTemplate>
<views:ListItemView />
</BindableLayout.ItemTemplate>
</StackLayout>
</Grid>
</ContentPage>
I solved this in a similar way. I did create a separate DataTemplate, but not in its own file. The addition I made was to add an x:DataType attribute.
<DataTemplate x:Key="myLabel" x:DataType="x:String">
<StackLayout>
<Label Text="{Binding .}" />
</StackLayout>
</DataTemplate>
Im developing a Xamarin.Forms application for both IOS and Android. My code in the XAML file is like this:
<StackLayout BackgroundColor="White" Padding="1" VerticalOptions="FillAndExpand">
<Image HeightRequest="150" Aspect="AspectFill" Source="{Binding Post.ImageUrl}" />
<Label Text="{Binding Post.Title}" VerticalOptions="FillAndExpand" FontFamily="{StaticResource BoldFont}" FontSize="20" />
<Label Text="{Binding Post.CreatedOn}" VerticalOptions="FillAndExpand" FontFamily="{StaticResource NormalFont}" FontSize="12" />
<WebView x:Name="WebViewer" HeightRequest="500" VerticalOptions="FillAndExpand" BackgroundColor="White">
<WebView.Source>
<HtmlWebViewSource Html="{Binding Post.Data.Content}" />
</WebView.Source>
</WebView>
<Label Text="Comments" FontSize="12" />
</StackLayout>
When I simulate the application, only the Webview Scrolls and all the other elements stay fixed in place. Theres another similar question on Stackoverflow, but the solution doesn't work and it doesnt answer my question for IOS, it is only targetted for Android.
This image shows the webview scrolling, and it's siblings staying in place
I would like that they all scroll together so that it acts like one page. This should be a crossplatform solution, so I only have to write the code once for both IOS and Android. How can I achieve this?
You can try something like that
Design Side
<?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="XamarinTest.View.WebViewDemo">
<ContentPage.Content>
<ScrollView>
<StackLayout BackgroundColor="White" Padding="1" VerticalOptions="FillAndExpand">
<Image HeightRequest="150" Aspect="AspectFill" Source="home" />
<Label Text="Header" FontSize="20" />
<Label Text="Subheader" FontSize="12" />
<WebView Source="http://www.google.com" x:Name="WebViewer" BackgroundColor="White">
</WebView>
<Label Text="Comments" FontSize="12" />
</StackLayout>
</ScrollView>
</ContentPage.Content>
</ContentPage>
Coding Side
using System;
using System.Collections.Generic;
using Xamarin.Forms;
namespace XamarinTest.View
{
public partial class WebViewDemo : ContentPage
{
public WebViewDemo()
{
InitializeComponent();
}
protected override void OnAppearing()
{
base.OnAppearing();
}
protected override void OnSizeAllocated(double width, double height)
{
base.OnSizeAllocated(width, height);
WebViewer.HeightRequest = height;
WebViewer.WidthRequest = width;
}
}
}
I'm new to Xamarin.Forms and Xaml and this. I have made a custom control i would like to utilize as a custom background throughout my app. The custom control is made as a contentview and looks like this.
<ContentView.Content>
<ScrollView>
<StackLayout>
<RelativeLayout Padding="0" BackgroundColor="Teal" VerticalOptions="Start">
<Image Source="TopBG" BackgroundColor="Purple" Aspect="Fill" RelativeLayout.WidthConstraint="{ConstraintExpression Type=RelativeToParent, Property=Width, Factor=1}" RelativeLayout.HeightConstraint="{ConstraintExpression Type=RelativeToParent, Property=Width, Factor=0.6}" />
</RelativeLayout>
<Frame Padding="0" Margin="0,-25,0,0" CornerRadius="25" BackgroundColor="{StaticResource Key=Charcoal}">
<StackLayout Margin="0,0,0,0" VerticalOptions="StartAndExpand" BackgroundColor="Transparent" x:Name="InnerStack">
<!--I can insert custom controls here, but htat would determine this custom contentView for one purpose only-->
</StackLayout>
</Frame>
</StackLayout>
</ScrollView>
</ContentView.Content>
The custom control is then implemented on my ContentPage as such:
<ContentPage.Content>
<CustomLayouts:ContentBackground>
<!-- I would instead like to be able to add content here, and have it go into the stacklayout of the custom view.
This way i could utilize the same background but have different content go into it depending on my wishes -->
</CustomLayouts:ContentBackground>
</ContentPage.Content>
If i add a label inside that later example it just overrides everything and places a label, but not as intended inside the designated inner stackview of my ContentBackground.
The only thing i can think of is figuring some way of accesing the InnerStackView of my custom contentBackground, then accesing the children property of that Stacklayout and then Children.add(View) to that stack layout. Allthough this means i will have to do it from code and i would like to achieve this behaviour in XAML since that is more familiar to me.
Is this the only way or is there an alternative to achieve my goal in XAML?
Try use ContentProperty.Simple example:
[ContentProperty("AddContent")]
public class YourView: ContentView
{
protected ContentView ContentContainer;
public View AddContent
{
get => ContentContainer.Content;
set => ContentContainer.Content = value;
}
......
}
//in xaml
<YourView>
<Label Text="Hello world"/>
</YourView>
In case someone still trying this, you can use ControlTemplate to have a view on multiple pages or app wide,
<Application xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" x:Class="SimpleTheme.App">
<Application.Resources>
<ResourceDictionary>
<ControlTemplate x:Key="TealTemplate">
<Grid>
...
<BoxView ... />
<Label Text="Control Template Demo App"
TextColor="White"
VerticalOptions="Center" ... />
<ContentPresenter ... />
<BoxView Color="Teal" ... />
<Label Text="(c) Xamarin 2016"
TextColor="White"
VerticalOptions="Center" ... />
</Grid>
</ControlTemplate>
<ControlTemplate x:Key="AquaTemplate">
...
</ControlTemplate>
</ResourceDictionary>
</Application.Resources>
</Application>
The magic here is the ContentPresenter, you can place anything inside it will appear just fine. Then to use the desired template, set it for your ContentView.ControlTemplate like so,
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" x:Class="SimpleTheme.HomePage">
<ContentView x:Name="contentView" Padding="0,20,0,0"
ControlTemplate="{StaticResource TealTemplate}">
<StackLayout VerticalOptions="CenterAndExpand">
<Label Text="Welcome to the app!" HorizontalOptions="Center" />
<Button Text="Change Theme" Clicked="OnButtonClicked" />
</StackLayout>
</ContentView>
</ContentPage>
Checkout the official docs here.
If you want to create a custom control/layout that you can insert on any page, then you can create your own ContentView with ContentPresenter that will hold your views children,
<!-- Content -->
<ContentPresenter Content="{Binding SomeContent}"/>
where SomeContent can be a BindableProperty of type View.
You can also see an example of custom layouts here.
I have a problem with my project, I'm using MasterDetailPage with a simple ListView and using a local namespace to call another page inside of him with a ListView too, and have THIS result, the problem is, that white space between the toolbar and the listview, but if I try to navigate for this very page without using the MasterDetailPage, the listview works fine without this white space, and you check HERE
App.cs navigates to MenuPage.Xaml
MainPage = new NavigationPage(new MenuPage());
MenuPage.XAML
`<MasterDetailPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="Gone.MenuPage"
xmlns:local="clr-namespace:Gone;assembly=Gone">
<MasterDetailPage.Master>
<ContentPage Title="Menu">
<ListView BackgroundColor="Transparent"
SeparatorVisibility="Default"
HasUnevenRows="True"
x:Name="listView">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<StackLayout Padding="2" Orientation="Horizontal">
<Image Aspect="Fill" WidthRequest="60" HeightRequest="60" Source="{Binding image}"/>
<StackLayout Padding="5,18,0,0" Orientation="Vertical">
<Label TextColor="Black" Text="{Binding title}"/>
</StackLayout>
</StackLayout>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</ContentPage>
</MasterDetailPage.Master>
<MasterDetailPage.Detail>
<local:MainPage/>
</MasterDetailPage.Detail>
</MasterDetailPage>`
MainPage.Xaml
<ListView BackgroundColor="Transparent"
SeparatorVisibility="Default"
HasUnevenRows="True"
x:Name="listView">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<StackLayout Orientation="Horizontal">
<Image Aspect="AspectFill" WidthRequest="130" HeightRequest="130" Source="{Binding image}"/>
<StackLayout Padding="20" Orientation="Vertical">
<Label LineBreakMode="WordWrap" FontSize="17" TextColor="#4CAF50" Text="{Binding title}"/>
<Label FontAttributes="Bold" TextColor="#2962FF" Text="{Binding price}"/>
<Label TextColor="#455A64" Text="{Binding date}"/>
</StackLayout>
</StackLayout>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
A temporary solution is
Creating a CustomMasterDetailRenderer in your Android Project:
[assembly: ExportRenderer(typeof(MasterDetailPage), typeof(CustomMasterDetailRenderer))]
namespace Your.Name.Space
{
public class CustomMasterDetailRenderer : MasterDetailPageRenderer
{
public override void AddView(Android.Views.View child)
{
child.GetType().GetRuntimeProperty("TopPadding").SetValue(child, 0);
var padding = child.GetType().GetRuntimeProperty("TopPadding").GetValue(child);
base.AddView(child);
}
}
}
Maybe is needed set Padding 0 in your view.
Thanks to Sylvia Martinez:
https://forums.xamarin.com/discussion/comment/244966/#Comment_244966
This happens if you use MasterDetailPage with NavigationPage.
Don't declare MasterDetailPage as new NavigationPage(new MasterDetailPage()).
Instead declare MasterDetailPage as var masterDetailPage = new MasterDetailPage().
After that use masterDetailPage.Detail = new NavigationPage(new ContentPage());
So if you have navigation both through masterDetail and navigation, you will come up with several NavigationPages. And you won't be able to use just Navigation.PushAsync(somePage). Instead of it you will have to use the current NavigationPage instance like: ((NavigationPage)(this.Detail)).PushAsync(new ContentPage());