Why .NET-Maui Global Styles are not working? - xamarin

I have declared global styles in .Net Maui and trying to access it from one of the pages but it's throwing exceptions
Microsoft.Maui.Controls.Xaml.XamlParseException: Position 10:37. Type converter failed: Exception has been thrown by the target of an invocation.
Microsoft.Maui.Controls.Xaml.XamlParseException: Position 8:34. StaticResource not found for key Primary.
App.xaml code
<?xml version = "1.0" encoding = "UTF-8" ?>
<Application xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:MyApp"
x:Class="MyApp.App">
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="Resources/Styles/Colors.xaml" />
<ResourceDictionary Source="Resources/Styles/Styles.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
<Style x:Key="redLabelStyle"
TargetType="Label">
<Setter Property="TextColor"
Value="Red"/>
<Setter Property="FontSize"
Value="Small"/>
<Setter Property="FontAttributes"
Value="Bold"/>
</Style>
<Style TargetType="Label">
<Setter Property="TextColor"
Value="Green"/>
<Setter Property="FontSize"
Value="Small"/>
<Setter Property="FontAttributes"
Value="Bold"/>
</Style>
</Application.Resources>
MainPage.xaml code
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
NavigationPage.HasNavigationBar="False"
x:Class="MyApp.MainPage">
<VerticalStackLayout HorizontalOptions="CenterAndExpand"
VerticalOptions="CenterAndExpand">
<Label Style="{StaticResource redLabelStyle}"
Text="Global Style Red Label"/>
<Label Text="GLobal Style Green Label"/>
<Label Text="GLobal Style Green Label"/>
</VerticalStackLayout>
</ContentPage>
Note: This is the default app created by .Net Maui.

This is the wrong place i think </ResourceDictionary>
Try this :
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="Resources/Styles/Colors.xaml" />
<ResourceDictionary Source="Resources/Styles/Styles.xaml" />
</ResourceDictionary.MergedDictionaries>
<Style x:Key="redLabelStyle"
TargetType="Label">
<Setter Property="TextColor"
Value="Red"/>
<Setter Property="FontSize"
Value="Small"/>
<Setter Property="FontAttributes"
Value="Bold"/>
</Style>
<Style TargetType="Label">
<Setter Property="TextColor"
Value="Green"/>
<Setter Property="FontSize"
Value="Small"/>
<Setter Property="FontAttributes"
Value="Bold"/>
</Style>
</ResourceDictionary>
</Application.Resources>
Also give the second style a name. <Style TargetType="Label"> a name in x:Key=""
Like
x:Key="greenLabelStyle"

You can also add global styles to the Styles.xaml file referenced in your MergedDictionaries
Please note the location of file
<ResourceDictionary Source="Resources/Styles/Styles.xaml" />
You can copy your styles directly into there instead, allowing you to keep all of your global styles in one central place. This helps keep your App.xaml nice and tidy.

Related

Standardize Xamarin Android Styles.xml and ResourceDictionary

I'm trying to avoid duplicate declaration of style definitions in both android styles.xml and resourcedictionary. For example,
In Android styles.xml, I've the following to change the default theme's primary color
<?xml version="1.0" encoding="UTF-8"?>
<resources>
<style name="MyDefaultTheme">
<item name="colorPrimary">#color/colorPrimary</item>
</style>
<color name="colorPrimary">#0E80FF</color>
</resources>
And in DefaultResourceDictionary.xaml, I've the following so that my XF's controls uses the same color as defined in styles.xml:
<ResourceDictionary ...>
<Color x:Key="colorPrimary">#0E80FF</Color>
</ResourceDictionary>
On top of my head, I can think of doing some PreBuild actions to invoke XmlPoke to insert the value from ResourceDictionary into styles.xml.
Is there any less complicated ways of doing it?
Yes you can add styles in the App Class.
Example adding this in the App.xaml file
<Application.Resources>
<ResourceDictionary>
<Color x:Key="PrimaryColor">#512bdf</Color>
<Color x:Key="SecondaryColor">White</Color>
<Style TargetType="Label">
<Setter Property="TextColor" Value="{DynamicResource PrimaryColor}" />
<Setter Property="FontFamily" Value="OpenSansRegular" />
</Style>
<Style TargetType="Button">
<Setter Property="TextColor" Value="{DynamicResource SecondaryColor}" />
<Setter Property="FontFamily" Value="OpenSansRegular" />
<Setter Property="BackgroundColor" Value="{DynamicResource PrimaryColor}" />
<Setter Property="Padding" Value="14,10" />
</Style>
</ResourceDictionary>
</Application.Resources>

Mvvmcross Xamarin Forms Navigation page style not working

I'm trying to style Navigation page on xamarin forms app with Mvvmcross.
before "adding" mmvcross I've defined style in App.xaml as follows.
<Style TargetType="NavigationPage">
<Setter Property="BarBackgroundColor" Value="Black" />
<Setter Property="BarTextColor" Value="White" />
</Style>
and it worked. I got background color and text color as i defined. Then we "moved" to Mvvmcross - we added all needed backend code, changed all pages from ContentPage to MvxContentPage etc and... background color of navigation page stopped working on Android (I haven't tried on iOS). If i change BarTextColor in App.xaml changes apply, color is changed. if i change BackgroundColor it also works - all application background color is changed. but no matter what value i apply to BarBackgroundColor it is still white.
my App.xaml is as follows:
<?xml version="1.0" encoding="utf-8" ?>
<core:MvxFormsApplication xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:views="clr-namespace:MvvmCross.Forms.Views;assembly=MvvmCross.Forms"
xmlns:viewModels="clr-namespace:MvvmCross.ViewModels;assembly=MvvmCross"
xmlns:core="clr-namespace:MvvmCross.Forms.Core;assembly=MvvmCross.Forms"
xmlns:attributes="clr-namespace:MvvmCross.Forms.Presenters.Attributes;assembly=MvvmCross.Forms"
x:Class="ShowMeTheLogs.Core.FormsApp">
<core:MvxFormsApplication.Resources>
<!--Global Styles-->
<Color x:Key="ColorPrimary">#98C340</Color>
<Color x:Key="ColorError">#CF1212</Color>
<Color x:Key="ColorWarning">#E4AD17</Color>
<Color x:Key="ColorInfo">#1283CF</Color>
<Color x:Key="ColorDebug">#989898</Color>
<Style TargetType="NavigationPage">
<Setter Property="BarBackgroundColor" Value="{StaticResource ColorPrimary}" />
<Setter Property="BarTextColor" Value="White" />
</Style>
<Style x:Key="SubmitButton" TargetType="Button">
<Setter Property="BackgroundColor" Value="{StaticResource ColorPrimary}" />
<Setter Property="TextColor" Value="White" />
</Style>
<Style x:Key="circleButton" TargetType="Button">
<Setter Property="BackgroundColor" Value="{StaticResource ColorPrimary}" />
<Setter Property="BorderRadius" Value="50" />
<Setter Property="WidthRequest" Value="100" />
<Setter Property="HeightRequest" Value="100" />
<Setter Property="TextColor" Value="White" />
<Setter Property="FontSize" Value="50" />
</Style>
<Style x:Key="smallSquareButton" TargetType="Button">
<Setter Property="BackgroundColor" Value="{StaticResource ColorPrimary}" />
<Setter Property="WidthRequest" Value="100" />
<Setter Property="HeightRequest" Value="100" />
<Setter Property="TextColor" Value="White" />
<Setter Property="FontSize" Value="Micro" />
<Setter Property="HorizontalOptions" Value="Center" />
<Setter Property="VerticalOptions" Value="Center" />
</Style>
</core:MvxFormsApplication.Resources>
</core:MvxFormsApplication>
my App.xalm.cs is the simpliest as it can be:
public partial class FormsApp: MvxFormsApplication
{
public App()
{
InitializeComponent();
}
}
and the simpliest view:
<?xml version="1.0" encoding="utf-8" ?>
<views:MvxContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:views="clr-namespace:MvvmCross.Forms.Views;assembly=MvvmCross.Forms"
x:TypeArguments="viewModels:WebAppListViewModel"
x:Class="ShowMeTheLogs.Core.Views.WebAppListPage"
xmlns:bindings="clr-namespace:MvvmCross.Forms.Bindings;assembly=MvvmCross.Forms"
xmlns:viewModels="clr-namespace:ShowMeTheLogs.Core.ViewModels;assembly=ShowMeTheLogs.Core"
Title="Sample title"
NavigationPage.HasBackButton="False">
<ContentPage.ToolbarItems>
<ToolbarItem x:Name="AddNewApp" Order="Secondary" Text="Dodaj aplikacjÄ™" Priority="0" Command="{bindings:MvxBind NewWebAppCommand}"/>
</ContentPage.ToolbarItems>
<RelativeLayout Padding="0" VerticalOptions="FillAndExpand" HorizontalOptions="FillAndExpand">
<Non relevant="Code" />
</RelativeLayout>
</views:MvxContentPage>
I have literally no idea why it is not working. the only change in androud code was changing class RootActivity: CompatActivity to class RootActivity: MvxFormsAppCompatActivity
have enyone fought this problem before?
packages were obtained from NuGet
- MvvmCross (and MvvmCross.Forms) ver 6.2.2
- Xamarin ver 28.0.0
- Xamarin.Forms ver 3.4.0
In your MainActivity OnCreate method, make sure the two lines setting the Toolbar resource are before the base.OnCreate() call:
protected override void OnCreate(Bundle bundle)
{
TabLayoutResource = Resource.Layout.Tabbar;
ToolbarResource = Resource.Layout.Toolbar;
base.OnCreate(bundle);
}
https://github.com/MvvmCross/MvvmCross/issues/2301

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 use ResourceDictionary as StaticResource in Windows Phone 8 (element not fount)

I am creating a Windows Phone 8 app. In the app I have a ResourceDictionary defined in a XAML file as:
<Style TargetType="TextBlock">
<Setter Property="Foreground" Value="YellowGreen" />
<Setter Property="FontSize" Value="35" />
<Setter Property="TextWrapping" Value="Wrap"/>
</Style>
<Style TargetType="TextBox" x:Key="CommonSetters">
<Setter Property="Width" Value="450"/>
<Setter Property="FontSize" Value="35" />
<Setter Property="Foreground" Value="YellowGreen" />
<Setter Property="Height" Value="100"/>
<Setter Property="Background" Value="Red">
<!--<Setter.Value>
<ImageBrush ImageSource="logo.png" Opacity="0.1"/>
</Setter.Value>-->
</Setter>
</Style>
</ResourceDictionary>
This ResourceDictionary is referenced in App.xaml as:
xmlns:shell="clr-namespace:Microsoft.Phone.Shell;assembly=Microsoft.Phone">
<!--Application Resources-->
<Application.Resources>
<local:LocalizedStrings xmlns:local="clr-namespace:Work_Force" x:Key="LocalizedStrings"/>
<ResourceDictionary x:Key="myDict">
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="Resource.xaml"/>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
<Style TargetType="TextBlock" x:Key="NN">
<Setter Property="Width" Value="450"/>
<Setter Property="FontSize" Value="35" />
<Setter Property="Foreground" Value="YellowGreen" />
<Setter Property="Height" Value="100"/>
</Style>
</Application.Resources>
<Application.ApplicationLifetimeObjects>
<!--Required object that handles lifetime events for the application-->
<shell:PhoneApplicationService
Launching="Application_Launching" Closing="Application_Closing"
Activated="Application_Activated" Deactivated="Application_Deactivated"/>
</Application.ApplicationLifetimeObjects>
</Application>
And then the easy part of doing:
Static Resources NN work fine but commonSetters is not working it declared in resourse.xaml.
The way you defined your resources in App.xaml, your 'myDict' resource dictionary is a nested dictionary within Application.Resources default dictionary. I don't know of any syntax how you can reference resources in nested dictionaries in XAML (as I didn't need this ever yet; I think FindResource(...) from code behind can accomplish this). A way to fix your problem is, that you modify the Application.Resources' default dictionary directly to merge with your 'Resources' dictionary. You can do so by modifying the Application.Resources section:
<Application.Resources>
<ResourceDictionary>
<local:LocalizedStrings xmlns:local="clr-namespace:PhoneApp1" x:Key="LocalizedStrings"/>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="Resources.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
Note that now you don't have a ReosurceDictionary called 'myDict' anymore. Your 'Resources' dictionary will be directly merged into the default dictionary, that has no key. Then the resource will be resolved correctly.
finally i got the solution it similar like the aspx or html page, where we add the reference of the style in required page
in whereever you, it required to add the reference of the page in page where you have required
<phone:PhoneApplicationPage.Resources>
<ResourceDictionary Source="yourstylepage.xaml"/>
</phone:PhoneApplicationPage.Resources>
put the above code after <phone:PhoneApplicationPage>

Resources