PathGeometry in ResourceDictionary - xaml

In WPF I used to have my vector icons in ResourceDictionary like this:
<PathGeometry x:Key="BackIconGeometry">M9.5,0 L16,0 8.75,7 22,7 22,11 8.75,11 16,18 9.5,18 0,9 z</PathGeometry>
and reference it from application like this:
<Path Data="{StaticResource BackIconGeometry}" Style="..." />
In UWP I'm getting error:
A value of type 'String' cannot be added to a collection or dictionary
of type 'PathFigureCollection'
How can I store my icons data in resource dictionaries? I would like to avoid storing them as <Style TargetType="Path" /> since I would like to use different styles for the icons

Your Path is an actual string value that is used for Binding so instead of using PathGeometry use x:String in resource Dictionary.
<Application.Resources>
<x:String x:Key="BackIconGeometry">M9.5,0 L16,0 8.75,7 22,7 22,11 8.75,11 16,18 9.5,18 0,9 z</x:String>
</Application.Resources>
and in XAML you can use like below.
<Path Data="{StaticResource BackIconGeometry}" />

Related

AppThemeBinding an ImageButton's Source using Binding is not working

The template is defined as:
<ContentPage.Resources>
<DataTemplate x:Key="MenuOptionTemplate">
<controls:MenuButtonControl />
</DataTemplate>
</ContentPage.Resources>
<ScrollView Orientation="Vertical">
<FlexLayout
AlignContent="Start"
AlignItems="Start"
BindableLayout.ItemTemplate="{StaticResource MenuOptionTemplate}"
BindableLayout.ItemsSource="{Binding MenuOptions}"
JustifyContent="SpaceEvenly"
VerticalOptions="Start"
Wrap="Wrap" />
</ScrollView>
The MenuButtonControl is define as:
...
<ImageButton
Source="{AppThemeBinding Light={Binding LightImageSource},
Dark={Binding DarkImageSource}}"/>
...
MenuOptions is is dynamically generated based on the user's role, but basically each menu option is create like so:
new MenuOption {
Title = "My Title",
LightImageSource = "sample_light",
DarkImageSource = "sample_dark"
}
{Binding LightImageSource} does not work.
So what is the correct way to implement this?
Because AppThemeBinding.Light is a markup extension (inherit from IMarkupExtension) property and not a BindableProperty you cannot use DynamicResource or Binding with it.
Thus you cannot use AppThemeBinding in this case. But you can use bindings (without AppThemeBinding), converters.. (see answers on the linked question), you just need to add the logic to conditionally set the appropriate image source based on the active theme using:
Application.Current.RequestedTheme;
Binding image source dynamically on xamarin forms
AppThemeBinding source
RequestedTheme
Edit
To react on theme changes use the event rather than testing the property RequestedThemeChanged:
How to detect Xamarin Forms System Theme Change

How to access resource located in merged dictionary from code

I have a bunch of Colors inside a couple of ResourceDicitonaries like this:
<ResourceDictionary xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:s="clr-namespace:System;assembly=netstandard">
<Color x:Key="Color.Background">#301536</Color>
</ResourceDictionary>
And I simply add both to the App.xaml like so:
<!--Colors-->
<ResourceDictionary Source="Resources/Colors/Light.xaml"/>
<ResourceDictionary Source="Resources/Colors/Dark.xaml"/>
The ResourceDicitonary file is simply a .xaml file without any bundled .cs, and both of the two dictionaries are set on the App.xaml without having to define them inside a MergedDicionaries group.
When trying to access the a Color from the code, I'm not able to find it, looks like it was not added to the resource list.
var color = Application.Current.Resources.FirstOrDefault(f => f.Key == "Color.Background")
.Value as Color? ?? Color.Crimson;
Is there any way to access a resource like FindResource/TryFindResource available in WPF?
I also tried to access/see the contents of the MergedDictionaries but for some reason the merged dictionaries are always empty.
Thanks to another person I was able to construct this working code:
internal static Color TryGetColor(string key, Color fallback)
{
Application.Current.Resources.TryGetValue(key, out var color);
return color as Color? ?? fallback;
}
According to your description, you want to add multiple ResourceDictionary in APP.xaml, it doesn't work.
I find one article about this issue, you can take a look:
https://nicksnettravels.builttoroam.com/post/2018/09/02/Getting-Started-with-XamarinForms-and-Resource-Dictionaries.aspx

XAML Margin in resources

How do I define XAML margin in Windows universal app resources? I tried to define it as
<Thickness x:Key="MyMargin" Left="10" Top="20" Right="10" Bottom="20" />
by this does not compile, I get
XamlCompiler error WMC0100: XAML Thickness type cannot be constructed. In order to to be constructed in XAML, a type cannot be abstract, interface, nested, generic or a struct, and must have a public default constructor
The syntax for Windows XAML is as follows:
<Thickness x:Key="myMargin">10,20,10,20</Thickness>
which could be simplified to:
<Thickness x:Key="myMargin">10,20</Thickness>
I had it working by binding it to a String:
<x:String x:Key="MarginLeftPage" >120,0,0,0</x:String>
[...]
Grid Margin="{StaticResource MarginLeftPage}">

StaticProperties in Resource Dictionary

My XAML has been working fine, referencing a Static Property of a static class
<TextBox IsReadOnly="{x:Static loc:StateMachine.IsReadOnly}" />
I now want to refactor the above, so I can use a ResourceDictionary
So, my resource dictionary is
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:stat="clr-namespace:MyProjectHelper"
>
<stat:StateMachine x:Key="StaticResources" />
</ResourceDictionary>
On my XAML, I removed the namespace reference called loc (which I was using) and I add a reference to the resource dictionary (which works since my views show and converters do their job) but when I add the following code
<TextBox IsReadOnly="{StaticResource StaticResources.IsReadOnly}" />
I get a runtime exception
'Provide value on 'System.Windows.StaticResourceExtension' threw an exception.' Line number '50' and line position '97'.
My research shows this is something wrong wit the XML - it could be a typo (checked) or an unexpected value but I can't see what I need to do to fix this despite looking over SO and Google
I also tried
<TextBox IsReadOnly="{Binding Source={StaticResource StaticResources}, Path=IsReadOnly}" />
but the exception is
'The invocation of the constructor on type 'SeoHelper.StateMachine' that matches the specified binding constraints threw an exception.' Line number '9' and line position '6'.
{StaticResource } binding needs to be able to instantiate your class, and it had problem to do so because the class was static. Your last trial would've worked if only the class wasn't declared as static.
Possible workaround if you need to keep your class static is, you can register the property instead of the class to resource dictionary using StaticExtension :
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:stat="clr-namespace:MyProjectHelper"
>
<x:StaticExtension Member="stat:StateMachine.IsReadOnly" x:Key="StaticResources"/>
</ResourceDictionary>
Then binding to the resource can be done as usual :
<TextBox IsReadOnly="{StaticResource StaticResources}" />

Imagebrush ResourceDictionary

I've created an Resourcedictionary where i define my ImageBrush to an jpg picture. I use this ImageBrush on my Path object to fill it. However when I build I get the error Error:
Error HRESULT E_FAIL has been returned from a call to a COM component.
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:c="clr-namespace:System;assembly=mscorlib"
xmlns:Model="clr-namespace:MVVMTestApp.Model;assembly=MVVMTestApp.Model"
xmlns:View="clr-namespace:MVVMTestApp.View"
xmlns:ViewModel="clr-namespace:MVVMTestApp.ViewModel">
<c:Double x:Key ="StrokeUserControl">
2
</c:Double>
<ImageBrush x:Key="CountryBackground" ImageSource="../Assets/gra-bakgrund.jpg" Stretch="Fill"/>
And I'm trying to get it to fill in my Path object like this
Fill="{StaticResource CountryBackground}"