How can I change the NavigationPage TitleView in Xamarin Forms MasterDetailPage - xamarin

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>

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>

VerticalTextAlignment="End" doesn't align my text at the bottom of a <StackLayout>

I have this code:
<?xml version="1.0" encoding="utf-8"?>
<StackLayout xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:Japanese;assembly=Japanese"
x:Class="Japanese.Templates.HeaderTemplate"
x:Name="this" BackgroundColor="#efeff4" HorizontalOptions="FillAndExpand" Orientation="Vertical" Spacing="0" Margin="0">
<StackLayout HeightRequest="50" >
<Label Text="ABC" HorizontalOptions="Start" VerticalTextAlignment="End" Margin="20, 0, 0, 0" />
</StackLayout>
</StackLayout>
When it runs the text ABC appears at the top of the cell and not the bottom.
Can someone explain to me why it does not appear at the bottom when I use VerticalTextAlighment="End"
I also tried this but it still puts the text at the top of the StackLayout:
<?xml version="1.0" encoding="utf-8"?>
<StackLayout xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:Japanese;assembly=Japanese"
x:Class="Japanese.Templates.HeaderTemplate"
x:Name="this" BackgroundColor="#efeff4" HorizontalOptions="FillAndExpand" Orientation="Vertical" Spacing="0" Margin="0">
<StackLayout HeightRequest="50" >
<Label Text="ABC" HorizontalOptions="Start" VerticalTextAlignment="End"
VerticalOptions="End" Margin="20, 0, 0, 0" />
</StackLayout>
</StackLayout>
<ContentPage BackgroundColor="Purple" xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" xmlns:local="clr-namespace:test3" x:Class="test3.MainPage">
<StackLayout BackgroundColor="Yellow">
<!-- Place new controls here -->
<Label BackgroundColor="Pink" Text="I'm at the bottom!" HorizontalOptions="Center" VerticalOptions="EndAndExpand" />
</StackLayout>
</ContentPage>

Bind to ContentPage Title From ControlTemplate

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>

Structure xaml xamarin

I want to create a structure but it's not coming out the way I want it
<?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:local="clr-namespace:App37"
x:Class="App37.MainPage">
<StackLayout BackgroundColor="Aqua" VerticalOptions="Fill" HorizontalOptions="Fill">
</StackLayout>
<StackLayout BackgroundColor="Bisque" VerticalOptions="Fill" HorizontalOptions="Fill">
</StackLayout>
<StackLayout BackgroundColor="BlueViolet" VerticalOptions="Fill" HorizontalOptions="Fill">
</StackLayout>
</ContentPage>
My resolve has to stay this way
enter image description here
One smart way of doing this structure is through Grid layout
<?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:local="clr-namespace:XamarinFormDemo" x:Class="XamarinFormDemo.XamarinFormDemoPage">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="*" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<StackLayout HorizontalOptions="Fill" Grid.Row="0" BackgroundColor="Gray" />
<StackLayout HorizontalOptions="Fill" Grid.Row="1" BackgroundColor="Bisque" />
<StackLayout HorizontalOptions="Fill" Grid.Row="2" BackgroundColor="BlueViolet" />
</Grid>
</ContentPage>
As Jason pointed out, a ContentPage can have only once child element. You can have a parent stacklayout to hold the three child stacks e.g
<?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:local="clr-namespace:App37"
x:Class="App37.MainPage">
<StackLayout>
<StackLayout BackgroundColor="Aqua" VerticalOptions="Fill" HorizontalOptions="Fill">
</StackLayout>
<StackLayout BackgroundColor="Bisque" VerticalOptions="Fill" HorizontalOptions="Fill">
</StackLayout>
<StackLayout BackgroundColor="BlueViolet" VerticalOptions="Fill" HorizontalOptions="Fill">
</StackLayout>
</StackLayout>
</ContentPage>

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