XAML Preview in Visual Studio not showing title bar - visual-studio

I am working on designing some user interfaces for my project, and am noticing that the title bar that is displayed when I run my app is not present in the XAML Design Previewer. Not only that, the title bar apparently is throwing off the size of my elements. Is there any way to get the title bar to display in the preview so I can accurately design my UI? I am using Visual Studio 2019. Here is some code. I am also attaching screenshots of the preview vs the emulator.
I've tried explicitly setting the NavigationPage.HasNavigationBar property to true in the content page header of MainScreen.
I initiate AppShell and make it the MainPage of the app:
public App()
{
InitializeComponent();
MainPage = new AppShell();
}
This is the XAML of AppShell:
<?xml version="1.0" encoding="UTF-8"?>
<Shell 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:local="clr-namespace:MyApp.Views"
Title="MyApp"
x:Class="MyApp.AppShell"
>
<!--
Styles and Resources
-->
<Shell.Resources>
<ResourceDictionary>
<Color x:Key="NavigationPrimary">#2196F3</Color>
<Style x:Key="BaseStyle" TargetType="Element">
<Setter Property="Shell.BackgroundColor" Value="{StaticResource NavigationPrimary}" />
<Setter Property="Shell.ForegroundColor" Value="White" />
<Setter Property="Shell.TitleColor" Value="White" />
<Setter Property="Shell.DisabledColor" Value="#B4FFFFFF" />
<Setter Property="Shell.UnselectedColor" Value="#95FFFFFF" />
<Setter Property="Shell.TabBarBackgroundColor" Value="{StaticResource NavigationPrimary}" />
<Setter Property="Shell.TabBarForegroundColor" Value="White"/>
<Setter Property="Shell.TabBarUnselectedColor" Value="#95FFFFFF"/>
<Setter Property="Shell.TabBarTitleColor" Value="White"/>
</Style>
<Style TargetType="ShellItem" BasedOn="{StaticResource BaseStyle}" />
</ResourceDictionary>
</Shell.Resources>
<!-- Your Pages -->
<FlyoutItem Title="Home Page" x:Name="MainScreenFlyout">
<ShellContent ContentTemplate="{DataTemplate local:MainScreen }"/>
</FlyoutItem>
<FlyoutItem Title="Second Page" x:Name="SecondPage">
<ShellContent ContentTemplate="{DataTemplate local:LoadingScreen}"/>
</FlyoutItem>
</Shell>
This is the XAML of the MainScreen 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"
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.MainScreen"
xmlns:vm="clr-namespace:MyApp.ViewModels"
Title="MyApp">
<ContentPage.Resources>
<ResourceDictionary>
<Color x:Key="Primary">#2196F3</Color>
<Color x:Key="Accent">#96d1ff</Color>
<Color x:Key="LightTextColor">#999999</Color>
</ResourceDictionary>
</ContentPage.Resources>
<Grid Padding="0,25,0,25">
<Grid.RowDefinitions>
<RowDefinition Height="5*"></RowDefinition>
<RowDefinition Height="3*"></RowDefinition>
<RowDefinition Height="10*"></RowDefinition>
<RowDefinition Height="10*"></RowDefinition>
<RowDefinition Height="10*"></RowDefinition>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"></ColumnDefinition>
<ColumnDefinition Width="3*"></ColumnDefinition>
<ColumnDefinition Width="3*"></ColumnDefinition>
<ColumnDefinition Width="3*"></ColumnDefinition>
<ColumnDefinition Width="*"></ColumnDefinition>
</Grid.ColumnDefinitions>
</Grid>
</ContentPage>
Edit: My ultimate goal was to get the preview to show the same way that the emulator ultimately would, and I did find a work around to accomplish it. I will have to manually adjust for each new device, but that's a headache for when I am making it response.
The solution is to set a top margin in the ignorable http://xamarin.com/schemas/2014/forms/design namespace. I tried to find the heights and got some numbers but they didn't work for me so I fooled around with it until it matched up. 87 appears to be the magic number for my device.
<!--Title bars are 48 and 56 for android devices, 44 for iphone, but apparently that isn't right?-->
<Grid Padding="0,25,0,25" d:Margin="0,87,0,0" x:Name="MainScreenGrid">

Because the "Title bar" called also navigation bar is generated by Shell, while the previewer renders only MainPage.xaml file (not Application.MainPage which is Shell).
I believe Shell is still not handled properly in the previewer, as well as in emulator hot reload, future versions of VS will probably bring some enhancements. For example if you open AppShell.xaml in the previewer nothing interesting will be rendered only a blank page.
Update
xaml previewer has been completely removed in VS 16.9.0 Preview 4.0, it will be replaced with an enhanced Hot Reload.

Related

Xamarin: How to Add a Background Image to All Pages with an AspectFill property

Total newbie Xamarin user.
I'm trying to add a background image to all the pages in the mobile app.
This was a great resource: Xamarin.Forms How to add Backgroud Image on all pages in App
However, I'd like to adjust the Aspect property of the image to AspectFill, so it's not so scrunched up. This is where I'm having trouble.
<Application xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="MyApp.App">
...
<Application.Resources>
<ResourceDictionary>
<Style TargetType="ContentPage" ApplyToDerivedTypes="True" >
<Setter Property="BackgroundImageSource" Value="background_image.png" />
</Style>
...
This sets the background image. How do I adjust the Aspect property for all pages? I've tried nesting an <Image Aspect="AspectFill" /> tag within the Setter property tag, but VS gives a warning that the "property 'Value' is set more than once". Could someone help me out? I'm sure I'm making some dumb error or I've misunderstood something about Xamarin.
Thanks.
Yes, we can use the following method to set the BackgroundImageSource for all ContentPage in your app:
<Application.Resources>
<ResourceDictionary>
<Style TargetType="ContentPage" ApplyToDerivedTypes="True" >
<Setter Property="BackgroundImageSource" Value="background_image.png" />
</Style>
</ResourceDictionary>
</Application.Resources>
But we couldn't set the AspectFill property for it while Aspect is specifically a property of the Image control as jason said.
Of course,if you need a solution that allows you to change the AspectRatio and adjust the image you can use 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" x:Class="Pages.PhotoPage">
<Grid >
<Image Source="background.png" Aspect="AspectFit" />
<!-- Place here the rest of the layout for the page. -->
</Grid >
</ContentPage>
Or use the solution j-petty said:
<AbsoluteLayout VerticalOptions="FillAndExpand" HorizontalOptions="FillAndExpand">
<Image AbsoluteLayout.LayoutFlags="All" AbsoluteLayout.LayoutBounds="0, 0, 1, 1" Source="sample.jpg" Aspect="AspectFill"/>
<StackLayout AbsoluteLayout.LayoutFlags="All" AbsoluteLayout.LayoutBounds="1,1,1,1">
<!--Content-->
<StackLayout HorizontalOptions="CenterAndExpand" VerticalOptions="CenterAndExpand" >
<Label x:Name="KategoriePicker" Text="Was möchtest du essen?" BackgroundColor="White" />
<Label x:Name="OrtTextBox" Text="Dein Lieferort" BackgroundColor="White" />
</StackLayout>
</StackLayout>
</AbsoluteLayout>

Is there a way I can add resources to a page in the C# backend?

I have pages that look like 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:local="clr-namespace:Japanese;assembly=Japanese" xmlns:template="clr-namespace:Japanese.Templates" xmlns:t="clr-namespace:Japanese.Views.HelpTab.Xaml" x:Class="Japanese.Views.HelpTab.AssignMode" Title="Assign Mode Help" BackgroundColor="{DynamicResource PageBackgroundColor}">
<ContentPage.Content>
<ScrollView>
<StackLayout Spacing="0">
<StackLayout.Resources>
<Style TargetType="Frame" CanCascade="true">
<Setter Property="Style" Value="{StaticResource FrameBorder}" />
</Style>
<Style TargetType="Label" CanCascade="true">
<Setter Property="TextColor" Value="{DynamicResource HelpTextColor}" />
<Setter Property="Style" Value="{StaticResource HD}" />
</Style>
<Style TargetType="Grid" CanCascade="true">
<Setter Property="Style" Value="{StaticResource HG}" />
</Style>
</StackLayout.Resources>
There are about twenty pages in the application that all have the same set of Resources added but not every page.
Is there a way that I can add the resources in the C# backend of my own page and then usesenter code here that for those twenty pages so that all I would need to do is something like this:
<?xml version="1.0" encoding="UTF-8"?>
<MyContentPage xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" xmlns:local="clr-namespace:Japanese;assembly=Japanese" xmlns:template="clr-namespace:Japanese.Templates" xmlns:t="clr-namespace:Japanese.Views.HelpTab.Xaml" x:Class="Japanese.Views.HelpTab.AssignMode" Title="Assign Mode Help" BackgroundColor="{DynamicResource PageBackgroundColor}">
<ContentPage.Content>
<ScrollView>
<StackLayout Spacing="0">
Alternatively is there some way I could combine all those resources into just one and add that rather than adding the three individual styles?
Sure, there are a couple of things you can do in this area, but I think it will already help you a lot to know there are implicit and explicit styles.
Start by going to your App.xaml and add your styles there. You should see the <Application.Resources> node already there. You can add the <ResourceDictionary> in there and now define any resources or styles as you wish. Those will be available throughout the whole app.
For instance, in your case, like this:
<Application.Resources>
<ResourceDictionary>
<Style TargetType="Frame" CanCascade="true">
<Setter Property="Style" Value="{StaticResource FrameBorder}" />
</Style>
<Style TargetType="Label" CanCascade="true">
<Setter Property="TextColor" Value="{DynamicResource HelpTextColor}" />
<Setter Property="Style" Value="{StaticResource HD}" />
</Style>
<Style TargetType="Grid" CanCascade="true">
<Setter Property="Style" Value="{StaticResource HG}" />
</Style>
</ResourceDictionary>
</Application.Resources>
Because you are specifying the TargetType and not an x:Key, this is an implicit style. It will apply to all elements of that target type. There is two things you can do now; or create an inheritance of the control and apply the style only to that inheritance, or create an explicit style. You then add the x:Key="MyStyle" attribute to a style and add the Style="{StaticResource MyStyle}" to each element you want to apply the style to. More on styles can be read on the Microsoft Docs.
You can define resources in App.xaml and use in an entire project using
Application.Current.Resources["AppColor"];
If you want to use in xaml page the use like
<Label TextColor={Binding StaticResource AppColor}/>

Avoid to refer styles in all pages - Xamarin.Forms

I'm working on a Xamarin Forms app for mobile cross platform.
I found how to apply styles to my pages and controls in this way:
Styles/HeaderStyle.xaml
<?xml version="1.0" encoding="UTF-8"?>
<ResourceDictionary
xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="App.HeaderStyle">
<Style x:Key="Header" TargetType="StackLayout">
<Setter Property="Orientation" Value="Horizontal"/>
<Setter Property="Padding" Value="5"/>
<Setter Property="BackgroundColor" Value="Green"/>
</Style>
</ResourceDictionary>
Views/Page.xaml
<ContentPage
xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="App.HomePage"
xmlns:local="clr-namespace:App;"
NavigationPage.HasNavigationBar="false">
<ContentPage.Resources>
<ResourceDictionary MergedWith="local:HeaderStyle">
</ResourceDictionary>
</ContentPage.Resources>
<!-- Some other page content -->
</ContentPage>
I have some doubt about this implementation:
- I can't figure out how to add multiple style files
- I've to add the style file references to all the pages
I've tried to add the reference in App.xaml in some way like this
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="theme:Resources1"/>
<ResourceDictionary Source="theme:Resources2"/>
</ResourceDictionary.MergedDictionaries>
But without success.
If you have styles that you use everywhere, you can put them in a global style.
In your App.xaml you can define a ResourceDictionary just like you have now. For example:
<Application xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" x:Class="Styles.App">
<Application.Resources>
<ResourceDictionary>
<Style x:Key="buttonStyle" TargetType="Button">
<Setter Property="HorizontalOptions" Value="Center" />
<Setter Property="VerticalOptions" Value="CenterAndExpand" />
<Setter Property="BorderColor" Value="Lime" />
<Setter Property="BorderRadius" Value="5" />
<Setter Property="BorderWidth" Value="5" />
<Setter Property="WidthRequest" Value="200" />
<Setter Property="TextColor" Value="Teal" />
</Style>
</ResourceDictionary>
</Application.Resources>
</Application>
Then in your page you should be able to refer to them without having to declare the merging of the dictionary, like so:
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" x:Class="Styles.ApplicationStylesPage" Title="Application" Icon="xaml.png">
<ContentPage.Content>
<StackLayout Padding="0,20,0,0">
<Button Text="These buttons" Style="{StaticResource buttonStyle}" />
<Button Text="are demonstrating" Style="{StaticResource buttonStyle}" />
<Button Text="application style overrides" Style="{StaticResource buttonStyle}" />
</StackLayout>
</ContentPage.Content>
</ContentPage>
If you were to override the style, you could do so by declaring a style in that page, styles lower in the hierarchy take precendence over the styles higher up.
You could also choose not to add the x:Key attribute on a style to make it implicit. That way you do not have to declare the Style property on a control.

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.

Xamarin.Forms ImageButton Display Issue

I am trying to use an ImageButton in a StackLayout and attempting to set the text of the button to be set below the image. However, the text is always displayed on the right side of the image instead of below. here is the code:
<?xml version="1.0" encoding="utf-8" ?>
<StackLayout x:Class="MyApp.Portable.Controls.MyNavigationControl"
xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:controls="clr-namespace:XLabs.Forms.Controls;assembly=XLabs.Forms"
xmlns:forms="clr-namespace:Xamarin.Forms;assembly=Xamarin.Libraries.PCL"
x:Name="MyNavControl"
BackgroundColor="White"
HorizontalOptions="FillAndExpand"
MinimumHeightRequest="75"
Orientation="Horizontal">
<StackLayout.Resources>
<ResourceDictionary>
<Style x:Key="NavButtonStyle" TargetType="Button">
<Setter Property="BackgroundColor" Value="White" />
<Setter Property="TextColor" Value="Gray" />
<Setter Property="FontSize" Value="7" />
</Style>
</ResourceDictionary>
</StackLayout.Resources>
<forms:ImageButton x:Name="GpsButton"
Clicked="GpsBUttonClicked"
Image="GPS_Icon_Light_Gray_sm.png"
MinimumHeightRequest="75"
Orientation="ImageOnBottom"
Style="{StaticResource NavButtonStyle}"
Text="GPS"
VerticalOptions="Start" />
<StackLayout>
In case you haven't found it yet, here is the answer to your question. The problem is a matter of using the incorrect property to set the Image. The ImageButton.Image property will display the image however it will not adhere to any other set properties such as ImageButton.Orientation. To solve your issue you must set the ImageButton.Source property instead.
More info can be found here: https://github.com/XLabs/Xamarin-Forms-Labs/issues/235

Resources