I added CustomDataTemplateSelector to a ResourceDictionary in a separated file called DataTemplates.xaml which I subsequently linked in App.xaml
When I run the app, I get XamlParseException saying:
Type local:CustomDataTemplateSelector not found in xmlns clr-namespace:MyProject
On the other hand, when I put the content of DataTemplates.xaml to App.xaml, it works just fine.
App.xaml
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary Source="../DataTemplates.xaml"/>
DataTemplates.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"
xmlns:local="clr-namespace:MyProject">
<DataTemplate x:Key="FirstCell">
<Label Text="Some text"/>
</DataTemplate>
<DataTemplate x:Key="SecondCell">
<Label Text="Some other text"/>
</DataTemplate>
<local:CustomDataTemplateSelector
x:Key="CustomDataTemplateSelector"
SecondTemplate="{StaticResource SecondCell}"
FirstTemplate="{StaticResource FirstCell}"/>
I've confirmed the problem. (To clarify for others - the parse error occurs when attempt to run the app. During App.InitializeComponent.) I had xmlns:local ... on both App.xaml and DataTemplates.xaml.
To work-around this, use an alternative syntax for merging dictionaries, ResourceDictionary.MergedDictionaries:
<Application xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:ios="clr-namespace:Xamarin.Forms.PlatformConfiguration.iOSSpecific;assembly=Xamarin.Forms.Core"
xmlns:local="clr-namespace:XFSOAnswers"
x:Class="XFSOAnswers.App">
<Application.Resources>
<ResourceDictionary>
<Style TargetType="ContentPage" ApplyToDerivedTypes="True">
<Setter Property="ios:Page.UseSafeArea" Value="True"/>
</Style>
<ResourceDictionary.MergedDictionaries>
<local:DataTemplates />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
</Application>
In case it matters, here is what I had for DataTemplates:
DataTemplates.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"
xmlns:local="clr-namespace:XFSOAnswers">
<DataTemplate x:Key="FirstCell">
<Label Text="Some text"/>
</DataTemplate>
<DataTemplate x:Key="SecondCell">
<Label Text="Some other text"/>
</DataTemplate>
<local:CustomDataTemplateSelector
x:Key="CustomDataTemplateSelector"
SecondTemplate="{StaticResource SecondCell}"
FirstTemplate="{StaticResource FirstCell}"/>
</ResourceDictionary>
DataTemplates.xaml.cs:
using Xamarin.Forms;
using Xamarin.Forms.Xaml;
namespace XFSOAnswers
{
[XamlCompilation(XamlCompilationOptions.Compile)]
public partial class DataTemplates : ResourceDictionary
{
public DataTemplates()
{
}
}
}
(The original Source syntax should not need this .cs file. I don't know whether the syntax I used needs it or not.)
Related
How can I use Style Inheritance w/ multiple files? I've been able to utilize Stand-alone resource dictionaries but if a child style is BasedUpon a style in another file it isn't working.
In the example below, the ListView will have the specified SeparatorColor but not the BackgroundColor from the BasedUpon style.
BaseStyles.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">
<Color x:Key="LightPrimaryColor">LightPink</Color>
<Color x:Key="DarkPrimaryColor">DarkGreen</Color>
<Style x:Key="BaseColorStylePrimary" TargetType="View">
<Setter Property="BackgroundColor"
Value="{AppThemeBinding Light={StaticResource LightPrimaryColor}, Dark={StaticResource DarkPrimaryColor}}" />
</Style>
</ResourceDictionary>
SomeChildStyles.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">
<Style x:Key="ListViewStyleBasedOn"
TargetType="ListView"
BasedOn="{StaticResource BaseColorStylePrimary}">
<Setter Property="SeparatorColor"
Value="{AppThemeBinding Light=Orange, Dark=Red}" />
</Style>
</ResourceDictionary>
App.xaml
<?xml version="1.0" encoding="utf-8"?>
<Application xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="StyleInheritance.App">
<Application.Resources>
<ResourceDictionary Source="BaseStyles.xaml" />
<ResourceDictionary Source="SomeChildStyles.xaml" />
</Application.Resources>
</Application>
It looks like they made some changes a few years ago to achieve what I'm trying to do but when they introduced AppThemeBinding it wasn't expanded to handle this 🤔?
Add a code behind file w/ a call to InitializeComponent() to each separate resource file even though this blog post says it is no longer required.
Don't use the fancy clean way to remove extra code for defining <ResourceDictionary>'s
Updated BaseStyles.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"
<!--change is here-->
x:Class="StyleInheritance.BaseStyles">
<Color x:Key="LightPrimaryColor">LightPink</Color>
<Color x:Key="DarkPrimaryColor">DarkGreen</Color>
<Style x:Key="BaseColorStylePrimary" TargetType="View">
<Setter Property="BackgroundColor"
Value="{AppThemeBinding Light={StaticResource LightPrimaryColor}, Dark={StaticResource DarkPrimaryColor}}" />
</Style>
</ResourceDictionary>
BaseStyles.xaml.cs
using Xamarin.Forms;
namespace StyleInheritance
{
public partial class BaseStyles : ResourceDictionary
{ public BaseStyles() { InitializeComponent(); } }
}
SomeChildStyles.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"
<!--change is here-->
x:Class="StyleInheritance.SomeChildStyles">
<Style x:Key="ListViewStyleBasedOn"
TargetType="ListView"
BasedOn="{StaticResource BaseColorStylePrimary}">
<Setter Property="SeparatorColor"
Value="{AppThemeBinding Light=Orange, Dark=Red}" />
</Style>
</ResourceDictionary>
Added SomeChildStyles.xaml.cs
using Xamarin.Forms;
namespace StyleInheritance
{
public partial class SomeChildStyles : ResourceDictionary
{ public SomeChildStyles() { InitializeComponent(); } }
}
App.xaml
<?xml version="1.0" encoding="utf-8"?>
<Application xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="StyleInheritance.App">
<Application.Resources>
<!--change is here-->
<ResourceDictionary>
<ResourceDictionary Source="BaseStyles.xaml" />
<ResourceDictionary Source="SomeChildStyles.xaml" />
</ResourceDictionary>
</Application.Resources>
</Application>
I've created a full Sample project w/ some additional details in the readme.
Use MergedDictionaries to style with multiple files.
App.xaml:
<Application.Resources>
<ResourceDictionary>
<!--Global Styles-->
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="/Styles/Base.xaml" />
<ResourceDictionary Source="/Styles/Child.xaml" />
</ResourceDictionary.MergedDictionaries>
...
</ResourceDictionary>
</Application.Resources>
Base.xaml in folder Styles:
<?xml version="1.0" encoding="utf-8" ?>
<!--<?xaml-comp compile="true" ?>-->
<ResourceDictionary xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml">
<Style x:Key="BaseStyle" TargetType="Label">
<Setter Property="BackgroundColor" Value="Green" />
</Style>
</ResourceDictionary>
Child.xaml in folder Styles:
<?xml version="1.0" encoding="utf-8" ?>
<ResourceDictionary xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml">
<Style x:Key="ChildStyle" TargetType="Label" BasedOn="{StaticResource BaseStyle}">
<Setter Property="FontAttributes" Value="Italic" />
</Style>
</ResourceDictionary>
Sample XAML usage:
<Label Text="Background" Style="{StaticResource BaseStyle}"/>
<Label Text="Background+Italic" Style="{StaticResource ChildStyle}"/>
See also Better Resource Organization in Xamarin.Forms
Edit:
To use a Xaml ResourceDictionary without a partial class (code behind class) (as indicated by the x:Class attribute), remove the code behind class .xaml.cs file and the x:Class attribute. Please note that the property Build Action should be Embedded resource.
The properties should be observed in the project file:
<ItemGroup>
<EmbeddedResource Update="Styles\Child.xaml">
<Generator>MSBuild:UpdateDesignTimeXaml</Generator>
<!--<Generator>MSBuild:Compile</Generator>-->
</EmbeddedResource>
<EmbeddedResource Update="Styles\Base.xaml">
<Generator>MSBuild:UpdateDesignTimeXaml</Generator>
<!--<Generator>MSBuild:Compile</Generator>-->
</EmbeddedResource>
</ItemGroup>
I have a color defined in my App.xaml resource dictionary. When I try to reference it in a ContentView I get a run time exception:
StaticResource not found for key NavbarBackground
Do I need to merge the resource dictionary in App.xaml?
App.xaml
<Application.Resources>
<ResourceDictionary>
<!--Global Styles-->
...
<Color x:Key="NavbarBackground">Black</Color>
...
</ResourceDictionary>
</Application.Resources>
CustomTitleView.xaml
<ContentView>
...
<ContentView.Content>
...
<ImageButton Source="search.png" HorizontalOptions="Center"
VerticalOptions="CenterAndExpand" BackgroundColor="{StaticResource NavbarBackground}" />
...
</ContentView.Content>
</ContentView>
If you are using separate xaml file to define resources use ResourceDictionary. If you are settings values inside App.xaml set them inside Application.Resources. Refer to docs here
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>
I tried to use my custom IValueConverter which declared in the Xaml file.
The Converter Class was defined inside the EnglishKeyboard. The convert declared in a ResourceDictionary inside the xaml below. I tried to use this converter at the end of the code below
<ContentView xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:local="clr-namespace:ProjectorRemote"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="ProjectorRemote.EnglishKeyboard"
x:Name="englishKeyboard">
<ContentView.Resources>
<ResourceDictionary>
<local:EnglishKeyboard.StringCaseConverter x:Key="caseConverter">
</local:EnglishKeyboard.StringCaseConverter>
<!-- lower 1 characters -->
<x:String x:Key="lower_1">q</x:String>
<x:String x:Key="lower1_2">w</x:String>
<x:String x:Key="lower1_3">e</x:String>
<x:String x:Key="lower1_4">r</x:String>
<x:String x:Key="lower1_5">t</x:String>
<x:String x:Key="lower1_6">y</x:String>
<x:String x:Key="lower1_7">u</x:String>
<x:String x:Key="lower1_8">i</x:String>
<x:String x:Key="lower1_9">o</x:String>
<x:String x:Key="lower1_0">p</x:String>
</ResourceDictionary>
</ContentView.Resources>
<ContentView.Content>
<StackLayout
Orientation="Vertical"
HorizontalOptions="Fill"
VerticalOptions="End">
<Grid HorizontalOptions="Center" ColumnSpacing="1">
**<local:BaseKeyView
Grid.Column="0"
Text="{StaticResource lower1_1,
Converter={StaticResource caseConverter},
ConverterParameter={Binding IsUpper}}">
</local:BaseKeyView>**
It work with no error but the converter didn't get called after I changed to the code below
<local:BaseKeyView
Grid.Column="0"
Text="{StaticResource lower1_1,
Converter={StaticResource caseConverter},
ConverterParameter={Binding IsUpper}}">
</local:BaseKeyView>
I fixed the problem by changing to this
{Binding Source={StaticResource lower1_1}, Converter={ ..... –
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.