Bind xaml vector images dynamically - xaml

I'm looking for a way to bind xaml images dynamically in code.
There are lots of examples online to show how to bind png or xaml images in the window's xaml, or to load png files in code.
But I have found no examples for xaml files with build action=page. XmlReader can't handle them since they are compiled to baml.
LoadComponent(new Uri("...filename.baml") will apparently load the baml but what kind of image class do I load this into? BitmapImage(new Uri("...filename.baml") does not seem to work, probably because it's not a bitmap.
Thanks in advance.

Additionally, if your image is stored in a Xaml vector file in this kind of format:
You can load the individual xaml vector images in the following way (it is probably best to prevent the dictionary being added multiple times, if like me, you are loading it via an OpenFileDialog):
C#:
string fullPathAndFileName = "C:\Image_Name.xaml";
ResourceDictionary dict = new ResourceDictionary();
dict.Source = new Uri(fullPathAndFileName);
Application.Current.Resources.MergedDictionaries.Add(dict);
DrawingImage image = dict[dict.Keys.Cast().ToList()[0]] as DrawingImage;
myImage.Source = image;
Xml:
Image Height="200" Width="200" x:Name="myImage"

After much trial and error and searching, the following article helped me on my way:
Access ResourceDictionary items programmatically
If each Xaml vector image is contained inside a ResourceDictionary with a key (see my 2nd post below for the format)...
If your Xaml vector image files are all stored in your project (build action: page), you can load them in the following way:
//Get the ResourceDictionary using the xaml filename:
ResourceDictionary dict = System.Windows.Application.LoadComponent(new Uri("/yourprojectname;component/youriconfolder/youriconfilename.xaml", System.UriKind.Relative)) as ResourceDictionary;
//Get the xaml as a DrawingImage out the ResourceDictionary
DrawingImage image = dict[dict.Keys.Cast<object>().ToList()[0]] as DrawingImage;
I could return the image and bind it to the viewmodel property, which returns the iconfilename.xaml. Then I use a converter with the above code to lookup the icon and return it as a DrawingImage.
Or you can assign it as the source of an Image (see my 2nd post below).
UPDATE: 2015.10.08 - It seems Carl didn't get around to the "XAML format example" part of his post. The XAML would look something like this:
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<DrawingImage x:Key="SomeUniqueKey">
<DrawingImage.Drawing>
<DrawingGroup>
...
</DrawingGroup>
</DrawingImage.Drawing>
</DrawingImage>
</ResourceDictionary>
Then you could do:
DrawingImage image = dict["SomeUniqueKey"] as DrawingImage;
Or, if you prefer using the Image directly,
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Image x:Key="SomeUniqueImage">
<Image.Source>
<DrawingImage>
...
</DrawingImage>
</Image.Source>
</Image>
</ResourceDictionary>
And:
Image someImage = dict["SomeUniqueImage"] as Image;

Related

Xamarin.Forms loading Xaml with LoadFromXaml is not creating contained objects for a StackLayout

I'm trying to add to an existing xamarin.forms page, chunks of xaml that will be generated dynamically.
I'm starting my research using the following example from the official docs.
Everything works fine there, but when I try to change the string with the button def for a string with the stacklayout with the button inside, only the stacklayout is inflated, with no children at all.
That's weird, because you can inflate a full page in the example, but it looks like I'm missing something here.
Any advice about how to use LoadFromXaml for partial composite objects?
// MainPage.xaml.cs
void OnLoadButtonClicked(object sender, EventArgs e)
{
string navigationButtonXAML = "<StackLayout><Button Text=\"Navigate\" /></StackLayout>";
var sl = new StackLayout().LoadFromXaml(navigationButtonXAML);
_stackLayout.Children.Add(sl);
}
From the official doc, it's only using LoadFromXaml for single view or a complete contentPage, I also tried LoadFromXaml for layout, and it's loading the layout without its children. For loading layout with children, I'm try debugging with source code, will update later, and as a workaround, you can use layout with contentview like this:
string navigationStackLayoutXAML = "<?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:d=\"http://xamarin.com/schemas/2014/forms/design\" xmlns:mc=\"http://schemas.openxmlformats.org/markup-compatibility/2006\" mc:Ignorable=\"d\" x:Class=\"LoadRuntimeXAML.CustomerViewDemo\"> <ContentView.Content> <StackLayout > <Label Text=\"Hello Xamarin.Forms!\" /> <Button Text=\"SECONDB\"/> </StackLayout> </ContentView.Content> </ContentView>";
ContentView contentView = new ContentView().LoadFromXaml(navigationStackLayoutXAML);
_stackLayout.Children.Add(contentView);
Although it's xaml is a little bit more complex, but it can use predefined attributes just as in .xaml, also, elements inside the contentView will be accessible through:
Button secondB = contentView.FindByName<Button>("secondB");

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

Runtime change Resource Dictionary for a Windows 8.1 XAML Store App

I am trying to dynamically change my resource dictionary definitions for my application during run time.
I am doing this because I would like to have different font sizes, scaling etc for my application based on the view port size.
I currently have the following code which gets executed every time the view port size changes:
string stylesPath;
if (args.Type == "small")
{
stylesPath = "ms-appx:///Styles/small.xaml";
}
else
{
stylesPath = "ms-appx:///Styles/standard.xaml";
}
var resourceDictionary = new ResourceDictionary
{
Source = new Uri(stylesPath, UriKind.RelativeOrAbsolute)
};
Application.Current.Resources.MergedDictionaries.Clear();
Application.Current.Resources.MergedDictionaries.Add(resourceDictionary);
This works for the initial load. When I change my view port this code does get hit again, but after the resources dictionaries are cleared and reloaded my application's fonts/styles/etc don't change at all.
It appears that the application styles will only be loaded once during application start up.
Does anyone know of a way I can force my application to redraw itself based on the new resource dictionary values?
This can be accomplished using Themes. There is a handy nuget package, called Theme Manager, that makes it very easy to switch themes.
Instead of loading your themes on app load, put them in your app ThemeDictionaries
<ResourceDictionary.ThemeDictionaries>
<ResourceDictionary x:Key="Dark">
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="/Themes/small.xaml"/>
<ResourceDictionary Source="/Themes/standard.xaml"/>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</ResourceDictionary.ThemeDictionaries>
Then you can change the theme like such:
var url = new Uri(string.Format("ms-appx:///Themes/{0}.xaml", (args.Type == "small") ? "small" : "standard"));
ThemeManager.ChangeTheme(url);
You can read more about ThemeManager here.

Resizeing image (png) in windowsphone xaml without losing quality

In a listbox , i show flag icon for every row . and i use xaml image control in template of listbox item.
after resizing the png files ( flag icons ) , they lose their quality and they are not smooth any more ... what should i do with this problem ? for example in wpf there is a property RenderOptions.BitmapScalingMode for managing the quality . but i did not see anything in windows phone ... i was wondering if you guide me how can i fix this issue.
Thanks a lot
<Image Source="{Binding Icon}" Height="50" Width="50" Stretch="Fill" Margin="0,10,0,0"/>
RenderOptions.BitmapScalingMode does not exist in Windows-Phone.
But if you really want to do this code wise without vector images you can do it using Phone 8.1 SDK
Check out BitmapEncoder class. BitmapEncoder as part of the Windows.Graphics.Imaging Namespace.
BitmapEncoder.BitmapTransform.InterpolationMode is what you're looking for.
You could use the Bitmap to deliver the image with the same quality:
Image image = new Image();
Uri uri = new Uri(“images/single-pink-rose.png”, UriKind.Relative);
ImageSource img = new System.Windows.Media.Imaging.BitmapImage(uri);
image.SetValue(Image.SourceProperty, img);
Refer here for more: How to Reduce Size of Image in windows phone
How do I resize a BitmapImage to 50x50 on Windows Phone 7?
Hope it helps!

How to Assign a XAML Stype from Common/StandardStyles.xaml in code behind

I have search and tried a number of things to do this. I have a style that is successfully bound to multiple XAML frames by doing XAML code like this, the name of the style is ViewPersonTextboxDataStyle:
<TextBox Grid.Row="5" Grid.Column="1" Name="textboxName" Text="{Binding textboxName}" Margin="5,5,5,5" Style="{StaticResource ViewPersonTextboxDataStyle}"/>
So, when I get to another frame where I want to create the Grid rows and definitions in a code behind, I tried this, which I thought was correct:
var resourceDictionary = new ResourceDictionary()
{
Source = new Uri("ms-appx:///Common/StandardStyles.xaml", UriKind.Absolute)
};
var style = resourceDictionary["ViewPersonTextboxDataStyle"] as Style;
textBlock.Style = resourceDictionary["ViewPersonTextboxDataStyle"] as Style;
So at this point, I can see the style was found in the resource dictionary as style is populated correctly. But assigning into textBlock.Style causes a Catastrophic Exception. So, either I am missing a step or this is incorrect.
Not alot of net information on this.
Ok, thank you Raghavendra, this did point me in the right direction to tell me that things I was trying weren't off base.
What I ended up with is:
style = Application.Current.Resources["ViewPersonTextDataStyle"] as Style;
textBlock.Style = style;
Raghavendra is right, you don't need to use resource manager, and you also don't need to define it in the local XAML. I used the above line to do it by assigning current in every one of my frames anyway.
So with that, my exception was one for an IDIOT (namely me). I should have been using my TEXTBLOCK style not my TEXTBOX style. Assigning a textbox style to the textblock was causing the exception.
Try this:
textBlock.style = this.Resources["ViewPersonTextboxDataStyle"] as Style;
You need not use ResourceDictionary
Edit:
this.Resources refers to Page.Resources (that is in case the ViewPersonTextboxDataStyle is defined in Page.Resources we use this)
Try this one:
textBlock.style = App.Current.Resources["ViewPersonTextboxDataStyle"] as Style;