How to get/overwrite the styles defined inside the styles.xml (or any other default Xamarin style files) from outside the Xamarin app? - xamarin

I have an app that can be styled for different customers. I use the styles.xml to style the app for each customer. However, I need to compile the app, every time I need to change the styles. I want to avoid this by getting these style definition from an outside file configuration, and then apply them at run time. I´m already doing this for other resources like images and texts/labels.
Is this possible? How?
Regards

I'll give an example for a color.
If a style has <Setter Property="BackgroundColor" Value="{StaticResource Color1}" />, then that refers to a Resource with key Color1.
In App.xaml.cs, read the config, use it to construct a Color instance. then set that Resource:
Color color1 = ...;
Application.Current.Resources["Color1"] = color1;

My issue is for example for resources like "android:colorPressedHighlight" that are specified in the styles.xml in the Android project.
The ColorPressedHighlight field is const. It is Compile time constant and could not assign value at runtime.
MS official docs: https://learn.microsoft.com/en-us/dotnet/api/android.resource.attribute.colorpressedhighlight?view=xamarin-android-sdk-12

Related

How to globally add styles to some components

I would like to add some styles to some components for example v-chip I want to add some padding globally. I do not want to do it, or import a style file on each component that uses v-chip. I tried to add the styles to variables.scss it works fine but violate the caveats https://vuetifyjs.com/en/features/sass-variables/#caveats that produces duplicate css. Created a overwrites.scss file and add to it dose not work neither. Please if anyone know how to achieve it?
According to caveats CSS duplication is happened when you import any other stylesheet into variables.scss. As far as I understand, there is no any duplication happened when you haven't imported any CSS file. So, to configure variables in variables.scss is a good way to configure global styles.
If you need to configure styles which have no applicable variable (or you just prefer this way of styles configuration) you can:
a. Create your own component (e.g. XChip.vue) as a wrapper for v-chip.
<!-- XChip.vue -->
<template>
<v-chip v-bind="$attrs" v-on="$listeners">
...
</v-chip>
</template>
b. Add necessary styles in this component
<style scoped>
...
</styles>
c. Then use it everywhere in your project when you need a chip.
You can find more information how to pass down slots here: Vue - how to pass down slots inside wrapper component?

Xamarin.forms Stand-alone resource dictionaries don't update dynamically if there is no cs code behind file

Xamarin team introduced 2 different way of stand-alone-resource-dictionaries. Obviously there is a big difference but they neglected to write in their documentation.
Basically if i use without cs code behind file and without x:class defined as defined in the documentation and referencing like that in my page
<ResourceDictionary Source="GradientStyles.xaml"/>
GradientStyles.xaml look like below and i am updating GradientStartColor , GradientStopColor of PancakeView on runtime based on the theme selected.
<pancakeView:GradientStopCollection x:Key="BackgroundGradientStops">
<pancakeView:GradientStop Color="{StaticResource GradientStartColor}"
Offset="0"/>
<pancakeView:GradientStop Color="{StaticResource GradientStopColor}"
Offset="0.74"/>
</pancakeView:GradientStopCollection>
Implementation above just not working. It doesn't update Colors at all.
The same exact code;
Works in ContentPage.Resources directly. It will update
Works if i define a stand-alone-resource-dictionary with cs code behind file and implement on the page like this below
<ResourceDictionary.MergedDictionaries>
<resDics:GradientStyles />
</ResourceDictionary.MergedDictionaries>
There is that annotation in the documentation but i don't get what exactly it means.
This syntax doesnot instantiate the MyResourceDictionary class.
Instead, it references the XAML file.
Does it mean that it extends the contentpage using like partial class or inherits. Or is it cached only once and remains static? And when you use it with code behind class, it creates a new instance every time?
Finally is that a bug or feature? :)

Is there a way I can access a static resource in my C# code?

In my App.XAML I have this:
<Application xmlns:converters="clr-namespace:Japanese" xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" x:Class="Japanese.App">
<Application.Resources>
<Color x:Key="TextColor1">#123456</Color>
I can access this value in XAML like this:
<Style TargetType="Label">
<Setter Property="TextColor" Value="{StaticResource TextColor1}" />
</Style>
But is there also a way that I can access this in my back end C#
vm.C1BtnLabelTextColor = phrase.C1 == true ? Color.FromHex("#123456") : Color.FromHex("#0000FF");
For example here I would like to replace:
Color.FromHex("#123456")
with the value of the StaticResource
ResourceDictionary is a repository for resources that are used by a
Xamarin.Forms application. Typical resources that are stored in a
ResourceDictionary include styles, control templates, data templates,
colors, and converters.
In XAML, resources that are stored in a ResourceDictionary can then be
retrieved and applied to elements by using the StaticResource markup
extension. In C#, resources can also be defined in a
ResourceDictionary and then retrieved and applied to elements by using
a string-based indexer. However, there's little advantage to using a
ResourceDictionary in C#, as shared objects can simply be stored as
fields or properties, and accessed directly without having to first
retrieve them from a dictionary.
In short: ResourceDictionary is a Dictionary.
To read a value from a Dictionary you have to provide a Key. In your case the Key is "TextColor1". So using C# here is how you could read the value from Application.Resources:
var txtColor1 = (Color) Application.Current.Resources["TextColor1"];
Please note that you have to cast the returned value to a desired type, thats because the Dictionary is "generic".
You could also create an Extension Method if you have to reuse it in your project.
Source: Official documentation
You can access like this:
Application.Current.Resources["TextColor1"];
The solution proposed here (Application.Current.Resources["TextColor1"];) works only if you don't have ResourceDictionary.MergedDictionaries, otherwise, you need the following approach:
// helper method
private object GetResourceValue(string keyName)
{
// Search all dictionaries
if (Xamarin.Forms.Application.Current.Resources.TryGetValue(keyName, out var retVal)) {}
return retVal;
}
Exemple how to use:
ButtonColor = (Color) GetResourceValue("Primary");
This method will assure that all merged resources are iterated to find your current resource.
Reference: https://forums.xamarin.com/discussion/146001/how-to-get-a-rsource-from-an-mergeddictionary-in-c-code
This definitely works better especially when you are using MergedDictionaries

Appcelerator hierarchical selector for TSS

How can we set style using hierarchical selector in TSS?
For example in index.xml file I have
<TableView id="myTable">
<TableViewRow>
<Label text="Row"></Label>
</TableViewRow>
</TableView>
For this I want to set Set style to Label inside #myTable
Like in CSS we can do it
#myTable Label{
//style
}
But this is not working in TSS.
So does anyone know how can we set style using an hierarchical selector?
TSS isn't CSS, though both are designed to allow setting visual properties. I am almost positive there is no way to hierarchically set a TSS rule. You must apply to the object directly or to the object as a class. So, you could create a class called 'tablelabel' and set it's properties, then apply the class to the label object in the table... But it's a direct assignment not a hierarchical one.

WP7 - attempt to select and use application static resource in codebehind not working (no resources found)

With Windows Phone 7, I'm attempting to dynamically add controls to and object in codebehind, and apply a StaticResource to the new control.
Xaml file sample:
<phone:PhoneApplicationPage.Resources>
<ControlTemplate x:Key="PushpinControlTemplateBlue" TargetType="my2:Pushpin">
...
</ControlTemplate>
</phone:PhoneApplicationPage.Resources>
Codebehind sample:
>Pushpin myPush = new Pushpin();
>myPush.Location = new GeoCoordinate(52.569593, -0.9261151403188705);
>myPush.Content = "";
>myPush.Template = (ControlTemplate)Application.Current.Resources["PushpinControlTemplateBlue"];
>mapMain.Children.Add(myPush);
When I debug, and look at "Application.Current.Resources", there are no items in the collection, so the item is added to the controls list, but doesn't show up because it has no content.
Is there something simple I'm doing wrong? How do I correctly access the resource?
If the resource is defined within the page you need to the resources in the page and any defined at applicaiton level.
You can do this simply by refering to the Resources object within the page:
this.Resources["PushpinControlTemplateBlue"];
Application.Current.Resources is define in App.xaml not on a page. Place your template in
<Application.Resources>
Example

Resources