Bind to ContentPage Title From ControlTemplate - xamarin

I have a fairly simple Xamarin.Forms App, with a ContentPage and a ControlTemplate in an App.Xaml ResourceDictionary
I am trying to bind to the ContentPage.Title Property of the parent ContentPage. however the following doesn't seem to work..
ContentPage
<ContentPage
x:Class="Inhouse.Mobile.Pcl.Views.MoveLocationView"
xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
ControlTemplate="{StaticResource MainPageTemplate}"
Title="Move Location"
...
ControlTemplate
<?xml version="1.0" encoding="utf-8" ?>
<Application
x:Class="Inhouse.Mobile.Pcl.App"
xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml">
<Application.Resources>
<ResourceDictionary>
<ControlTemplate x:Key="MainPageTemplate">
<cut for Brevity ...>
<StackLayout BackgroundColor="#333333">
<Label Text="{TemplateBinding Page.Title}"></Label>
</StackLayout>
<ScrollView Grid.Row="2" >
<ContentPresenter VerticalOptions="FillAndExpand" HorizontalOptions="FillAndExpand" />
</ScrollView>
</ControlTemplate>
</ResourceDictionary>
</Application.Resources>
</Application>
I'm not sure what i should actually be binding too
i.e my attempt was
<Label Text="{TemplateBinding Page.Title}"></Label>

My problem was that i was in a StackLayout and needed to set
HorizontalOptions="StartAndExpand" so i could see it.
Additionally, Title was sufficient
{TemplateBinding Title}
I.e
<StackLayout Grid.Row="1" BackgroundColor="#333333">
<Label Text="{TemplateBinding Title}" TextColor="AliceBlue" HorizontalOptions="StartAndExpand"/>
</StackLayout>

Related

Xamarin, custom control with layout with accepts bindable content at a specific location

I need to create a standard layout which I can use on a number of pages, but pass in content which is shown inside... I'm having limited success...
Here's how I'm calling the custom control...
<?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:control="clr-namespace:myApp"
x:Class="myApp.MainPage">
<StackLayout>
<control:CustomPopupLayoutControl
BackgroundColor="LightGreen">
<control:CustomPopupLayoutControl.Content>
<Button Text="Hello" />
<!-- lots of other controls, buttons, labels etc, layout -->
</control:CustomPopupLayoutControl.Content>
</control:CustomPopupLayoutControl>
</StackLayout>
</ContentPage>
So you can see here I wan't to display some content..
Here's my custom control...
<?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="myApp.CustomPopupLayoutControl"
x:Name="CustomPopupLayouts">
<ContentView.Content>
<StackLayout BackgroundColor="LightBlue" Margin="30">
<Button Text="Close" /><!-- important-->
<!-- lots of other layout -->
<StackLayout BackgroundColor="Red" x:Name="Inner">
</StackLayout>
</StackLayout>
</ContentView.Content>
</ContentView>
So I'd like to show my hello button inside the Inner stack layout, I'll also need binding to work...
So the final page should look like...
<page>
<StackLayout BackgroundColor="LightBlue" Margin="30">
<Button Text="Close" /><!-- important-->
<StackLayout BackgroundColor="Red">
<button text="Hello">
</StackLayout>
<StackLayout>
</page>
Since you had defined a Button in Custom Control , You just need to pass the Title that you want to display on the Button from ContentPage to Custom Control.
in CustomPopupLayoutControl.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="myApp.CustomPopupLayoutControl"
x:Name="CustomPopupLayouts">
<ContentView.Content>
<StackLayout BackgroundColor="LightBlue" HeightRequest="450" Margin="30">
<Button HeightRequest="150" WidthRequest="80" Text="{Binding Source={x:Reference CustomPopupLayouts}, Path=ButtonTitle}" /><!-- important-->
<StackLayout BackgroundColor="Red" HeightRequest="300" x:Name="Inner">
</StackLayout>
</StackLayout>
</ContentView.Content>
</ContentView>
in CustomPopupLayoutControl.xaml.cs
Define a bindable property
public static BindableProperty ButtonTitleProperty =
BindableProperty.Create(nameof(ButtonTitle), typeof(string), typeof(CustomPopupLayoutControl),string.Empty);
public string ButtonTitle
{
get => (string)GetValue(ButtonTitleProperty);
set => SetValue(ButtonTitleProperty, value);
}
in ContentPage
You could set the title of button directly or use data binding .
<control:CustomPopupLayoutControl ButtonTitle = "Hello World!" BackgroundColor="LightGreen" / >
I've found a solution :)
<?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="myapp.CustomPopupLayoutControl"
x:Name="CustomPopupLayouts">
<ContentView.ControlTemplate>
<ControlTemplate>
<StackLayout BackgroundColor="LightBlue" Margin="30">
<Frame CornerRadius="5" Margin="20" HasShadow="False"
BackgroundColor="Red">
<StackLayout>
<Button Text="Close"
Command="{TemplateBinding
Parent.BindingContext.NavigateCommand}" />
<!-- important-->
<ContentPresenter />
</StackLayout>
</Frame>
</StackLayout>
</ControlTemplate>
</ContentView.ControlTemplate>
</ContentView>
.
<?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:control="clr-namespace:myapp"
x:Class="myapp.MainPage">
<StackLayout>
<control:CustomPopupLayoutControl BackgroundColor="LightGreen">
<StackLayout>
<Button Text="Hello" Command="{Binding NavigateCommand}" />
<Button Text="Goodbye" />
</StackLayout>
</control:CustomPopupLayoutControl>
</StackLayout>
</ContentPage>

How can I change the NavigationPage TitleView in Xamarin Forms MasterDetailPage

By default a MasterDetailPage adds the Title of the NavigationPage to the top of the view. I tried a simple experiment but it didn't work. It still renders the title instead of replacing it with an image. Is there a simple way to override the title area?
<MasterDetailPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:d="http://xamarin.com/schemas/2014/forms/design"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
xmlns:views="clr-namespace:MyApp.Views"
x:Class="MyApp.Views.MainPage">
<MasterDetailPage.Master>
<views:MenuPage />
</MasterDetailPage.Master>
<MasterDetailPage.Detail>
<NavigationPage>
<NavigationPage.TitleView>
<StackLayout>
<Image Source="MyAppLogo.png" HorizontalOptions="CenterAndExpand" WidthRequest="50" HeightRequest="50" Aspect="AspectFill" />
</StackLayout>
</NavigationPage.TitleView>
<NavigationPage.Icon>
<OnPlatform x:TypeArguments="FileImageSource">
<On Platform="iOS" Value="tab_feed.png"/>
</OnPlatform>
</NavigationPage.Icon>
<x:Arguments>
<views:JobsPage />
</x:Arguments>
</NavigationPage>
</MasterDetailPage.Detail>
</MasterDetailPage>
Update
So I discovered that each content page has to individually override the NavigationPage.TitleView. But the goal is to have the same title bar across all content pages. So I followed the recomendation here: https://forums.xamarin.com/discussion/167655/it-is-possible-to-creatre-a-navigationpage-titleview-for-all-contentpage. I've implemented this however I'm not seeing anything in the title bar at all. What am I doing wrong now?
App.xaml
<Application xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:d="http://xamarin.com/schemas/2014/forms/design"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:MyApp.Views"
mc:Ignorable="d"
x:Class="MyApp.App">
<Application.Resources>
<ResourceDictionary>
<!--Global Styles-->
<Color x:Key="NavigationPrimary">#2196F3</Color>
<Color x:Key="NavbarBackground">Black</Color>
<Style TargetType="NavigationPage">
<Setter Property="BarBackgroundColor" Value="{StaticResource NavbarBackground}" />
<Setter Property="BarTextColor" Value="White" />
</Style>
<local:CustomTitleView x:Key="CustomTitleView"/>
<Style TargetType="ContentPage" x:Key="CustomTitle">
<Setter Property="NavigationPage.TitleView" Value="{StaticResource CustomTitleView}"/>
</Style>
</ResourceDictionary>
</Application.Resources>
</Application>
CustomTitleView.xaml
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:d="http://xamarin.com/schemas/2014/forms/design"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
x:Class="BuildPro.Views.CustomTitleView">
<ContentPage.Content>
<StackLayout>
<Label Text="Hello world!" />
</StackLayout>
</ContentPage.Content>
</ContentPage>
MyContentPage.xaml
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:d="http://xamarin.com/schemas/2014/forms/design"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
x:Class="MyApp.Views.MyPage"
xmlns:vm="clr-namespace:MyApp.ViewModels"
Style="{StaticResource CustomTitle}" >
<ContentPage.BindingContext>
<vm:MyViewModel />
</ContentPage.BindingContext>
<ContentPage.Content>
<StackLayout>
<Label Text="Welcome to the Xamarin-Forms!"
VerticalOptions="CenterAndExpand"
HorizontalOptions="CenterAndExpand" />
</StackLayout>
</ContentPage.Content>
</ContentPage>
Update 2
I goofed up on the template for the title bar. Should have been a ContentView instead of ContentPage. Totally different class. Now this works:
CustomTitleView
<ContentView xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:d="http://xamarin.com/schemas/2014/forms/design"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
x:Class="MyApp.Views.CustomTitleView">
<ContentView.Content>
<StackLayout>
<Label Text="Hello world!" TextColor="AliceBlue" />
</StackLayout>
</ContentView.Content>
</ContentView>
You should add NavigationPage.TitleView in Xaml of each Detail Page (Usually Content Page), not in Xaml of MasterDetailPage.
Such as the Xaml of views:JobsPage can be modified as follow :
<?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:d="http://xamarin.com/schemas/2014/forms/design"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
x:Class="AppFormsMaster.Views.ItemsPage"
Title="{Binding Title}"
x:Name="BrowseItemsPage">
<NavigationPage.TitleView>
<StackLayout>
<Image Source="MyAppLogo.png" HorizontalOptions="CenterAndExpand" WidthRequest="50" HeightRequest="50" Aspect="AspectFill" />
</StackLayout>
</NavigationPage.TitleView>
<ContentPage.Content>
//...
//Content of Content Page
//...
</ContentPage.Content>
</ContentPage>
Then it will show the NavigationPage.TitleView .
For xamarin shell it should be Shell.TitleView
<Shell.TitleView>
<StackLayout Margin="10,10,0,10" Orientation="Horizontal">
<Image
BackgroundColor="LightBlue"
HeightRequest="25"
WidthRequest="25" />
<SearchBar HorizontalOptions="FillAndExpand" />
<Image
BackgroundColor="LightYellow"
HeightRequest="25"
WidthRequest="25" />
</StackLayout>
</Shell.TitleView>

Can I use something like a control template in Xamarin to surround a new object?

My application has objects that are surrounded by this:
<StackLayout HeightRequest="49" BackgroundColor="Red" Orientation="Vertical" Margin="0" >
<Grid VerticalOptions="CenterAndExpand">
     <!-- XAML here -->
    </Grid>
</StackLayout>
I would like to make it so that I don't need to enter the XAML on the 1st, 2nd, last and next to last lines each time.
Can I use something like a control template to avoid doing this and if so how would I use it?
You will need to use a combination of ContentPresenter and ControlTemplate (as mentioned in the note on this page)
On a ContentPage (or ContentView), the Content property can be assigned and the ControlTemplate property can also be set. When this occurs, if the ControlTemplate contains a ContentPresenter instance, the content assigned to the Content property will be presented by the ContentPresenter within the ControlTemplate.
<ControlTemplate x:Key="DefaultTemplate">
<StackLayout HeightRequest="49" BackgroundColor="Red"
Orientation="Vertical" Margin="0">
<Grid VerticalOptions="CenterAndExpand">
<ContentPresenter /> <!-- This line is replaced by actual content -->
</Grid>
</StackLayout>
</ControlTemplate>
Usage:
<ContentView ControlTemplate="{StaticResource DefaultTemplate}">
<!-- XAML here (basically the view that is to be surrounded by above layout) -->
<Label TextColor="Yellow" Text="I represent the content" />
</ContentView>
Yes, Xamarin also provide the Control Template functionalities in XAML.
Write a below code in App.xaml
<Application.Resources>
<ResourceDictionary>
<ControlTemplate x:Key="TealTemplate">
<Grid>
<Label Text="Control Template Demo App"
TextColor="White"
VerticalOptions="Center" />
</ControlTemplate>
</ResourceDictionary>
</Application.Resources>
Call the template in side ContentPage
<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>

Background Image out of proportion in xamarin.forms IOS

I've created an app using xamarin.forms. I just began testing the iOS side and my background image on the login screen looks zoomed in. On android the image displays correctly. Is there anything I need to change to get it to display correctly?
Mainpage.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="LoyaltyWorx.MainPage"
BackgroundImage="bk3.jpg"
>
<StackLayout VerticalOptions="FillAndExpand" HorizontalOptions="FillAndExpand">
<StackLayout Orientation="Horizontal" VerticalOptions="Start">
<!-- top controls -->
</StackLayout>
<StackLayout VerticalOptions="CenterAndExpand">
<!-- middle controls -->
<BoxView HeightRequest="430"></BoxView>
<Button Text="Continue with Facebook" x:Name="LoginBtn" BackgroundColor="#4867aa" TextColor="White" FontFamily="Klavika" HorizontalOptions="CenterAndExpand" Clicked="LoginBtn_Clicked" />
</StackLayout>
<StackLayout Orientation="Horizontal" VerticalOptions="End" HorizontalOptions="Center">
<!-- bottom controls -->
<Frame OutlineColor="White" HorizontalOptions="StartAndExpand">
<StackLayout Orientation="Horizontal" VerticalOptions="End" HorizontalOptions="Center">
<!-- bottom controls -->
<StackLayout Grid.Row="1" Orientation="Horizontal" Spacing="0">
<Label
Text="Terms and conditions"
FontSize="13"
TextColor="#71757a"
FontAttributes="Bold"
x:Name="LblTerms"/>
<Label
Text=" and"
FontSize="13"
TextColor="#71757a"
/>
<Label
Text=" privacy policy"
FontSize="13"
TextColor="#71757a"
FontAttributes="Bold"
x:Name="LblPrivacy"/>
</StackLayout>
</StackLayout>
</Frame>
</StackLayout>
</StackLayout>
</ContentPage>
Screenshots in both iOS and Android.
You can not play much on ContentPage Background image in In IOS its not picking up correctly. i will propose 2 solutions for you to get rid of this situation...
try both and get what matched to you
Solution 1
<?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="LoyaltyWorx.MainPage" >
<RelativeLayout>
<Image Source="bk3.jpg"
RelativeLayout.WidthConstraint=
"{ConstraintExpression Type=RelativeToParent, Property=Width}"
RelativeLayout.HeightConstraint=
"{ConstraintExpression Type=RelativeToParent, Property=Height}"/>
<PUT YOUR REST OF CODE HERE>
</RelativeLayout>
</ContentPage>
Solution 2
<?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="LoyaltyWorx.MainPage"
Padding="0">
<Grid>
<Image Source="bk3.jpg" Aspect="AspectFill" />
<StackLayout>
<PUT YOUR REST OF CODE HERE>
</StackLayout>
</Grid>
</ContentPage>
Update me with which suites you best....

how to define/override Style for ContentView when it is child of ContentPage

I have contentview as below
<?xml version="1.0" encoding="utf-8" ?>
<ContentView xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:convertors="clr-namespace:myApp.Convertors;assembly=myApp"
x:Class="myApp.cwPart">
<ContentView.Content>
<StackLayout Orientation="Horizontal"
BackgroundColor="White">
<RelativeLayout Style="{StaticResource myStyle}"
HorizontalOptions="Start"
VerticalOptions="Center">
I am referencing this ContentView inside multiple ContentPages as example one below. Every ContentPage should set different BackgroundColor, Height and Width. That's why I thought that style should be defined in the ContentPage but it is throwing error that it is not recognized. How can I achieve this?
PS, interesting thing I am using Gorilla player to achieve such changes and Gorilla player doesn't return any error :)
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:convertors="clr-namespace:myApp.Convertors;assembly=myApp"
xmlns:c="clr-namespace:myApp;assembly=myApp"
x:Class="myApp.AppLogsPage"
Title="{Binding AppName}"
x:Name="AppLogsPage">
<ContentPage.Resources>
<ResourceDictionary>
<Style x:Key="myStyle" TargetType="RelativeLayout">
<Setter Property="HeightRequest" Value="148"/>
<Setter Property="WidthRequest" Value="80"/>
<Setter Property="BackgroundColor" Value="White"/>
</Style>
</ResourceDictionary>
</ContentPage.Resources>
<ContentPage.Content>
<StackLayout x:Name="MainHolder">
<c:cwPart />
...
If I define ContentView Resources as below, it works fine but I am not able to override the Style defined inside ContentView
<?xml version="1.0" encoding="utf-8" ?>
<ContentView xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:convertors="clr-namespace:myApp.Convertors;assembly=myApp"
x:Class="myApp.cwPart">
<ContentView.Resources>
<ResourceDictionary>
<Style x:Key="myStyle" TargetType="RelativeLayout">
<Setter Property="HeightRequest" Value="148"/>
<Setter Property="WidthRequest" Value="80"/>
<Setter Property="BackgroundColor" Value="White"/>
</Style>
</ResourceDictionary>
</ContentView.Resources>
<ContentView.Content>
<StackLayout Orientation="Horizontal" BackgroundColor="White">
<RelativeLayout Style="{StaticResource myStyle}"
HorizontalOptions="Start" VerticalOptions="Center" >
There are many issues i would change in your approach but let's keep it simple. First of all i would use contentview with control template as;
in App.xaml;
<ControlTemplate x:Key="MyControlTemplate">
<StackLayout Orientation="Horizontal" BackgroundColor="White">
<RelativeLayout HorizontalOptions="Start" VerticalOptions="Center" />
</StackLayout>
</ControlTemplate>
then in your page.xaml
<ContentView ControlTemplate={StaticResource MyControlTemplate}/>
if you want to set individual styles for every page then you can create a control template for each of them.
To create a WPF like user control;
in App.xaml;
<ControlTemplate x:Key="MyControlTemplate">
<StackLayout Orientation="Horizontal" BackgroundColor="White">
<RelativeLayout HorizontalOptions="Start" VerticalOptions="Center" />
</StackLayout>
</ControlTemplate>
in the same project
public class CustomView: ContentView
{
public CustomView()
{
ControlTemplate = (ControlTemplate)Application.Current.Resources.FirstOrDefault(x => x.Key == "MyControlTemplate").Value;
}
}
then you can use CustomView control/view in any xaml page. Don't forget to add xaml namespace of the CustomView in consuming xaml page.

Resources