Xamarin forms shared project with images for Android and iOS - c#

I am trying to upload an image inside the Shared project in my solution so that the Android and iOS project can use it normally via Xaml. Not working, I do not know why. Can anyone explain why it is not working?
Extension:
[ContentProperty("Source")]
public class ImageResourceExtension : IMarkupExtension
{
public string Source { get; set; }
public object ProvideValue(IServiceProvider serviceProvider)
{
if (Source == null)
{
return null;
}
// Do your translation lookup here, using whatever method you require
var imageSource = ImageSource.FromResource(Source);
return imageSource;
}
}
Xaml:
<Image Source="{extensions:ImageResource MyProject.Assets.fechar.png}" HorizontalOptions="Start" HeightRequest="16" Focused="Image_Focused" BackgroundColor="Red" WidthRequest="15" />
Putting a breakpoint in the Extension it usually goes there once for each item in my list.
I've also tried inserting a hardcoded binding by codebehind only for testing and it also does not work using ImageSource.FromResource.
The image file is as EmbbedResource as the documentation indicates.

Don't use extension. There is much easier way.
According to Xamarin "Currently there is no implicit conversion for resource identifiers, you must use ImageSource.FromResource" and "Because there is no built-in type converter from string to ResourceImageSource, these types of images cannot be natively loaded by Xaml". So you cannot specify in xaml that your image is shared but you can use code behind to bind a shared image.
In xaml:
<Image Source="{Binding Image}" HorizontalOptions="Start" WidthRequest="80"/>
Then in code behind
public ImageSource Image
{
get
{
return ImageSource.FromResource("ButtonRendererDemo.Resources.icon1.png"); //from PCL
}
}
below is the project structure
//////////////////////////////////////////////////////////////////
Tested with shared project. Below is the structure
The key is to add reference of your shared project to your PCL where you are calling FromResource. The shared project gets injected into PCL
Then in my project structure it is
public ImageSource Image
{
get
{
//return ImageSource.FromResource("ButtonRendererDemo.Resources.icon1.png"); //from PCL
return ImageSource.FromResource("ButtonRendererDemo.Pictures.icon1.png"); //from Shared
}
}
//////////////////////////////////////////////////////////////
If nothing works for you use the follow code to find your resource. In the file where you call FromResource add using System.Reflection; then add the follow code
var assembly = typeof(App).GetTypeInfo().Assembly;
foreach (var res in assembly.GetManifestResourceNames())
{
System.Diagnostics.Debug.WriteLine("found resource: " + res);
}
You should see in Output window something like
found resource: someNamespace.Pictures.icon1.png - That's your resource you need to use.
You didn't answer my question about your project structure. Then I could give you an exact answer. I suspect that your path to image is "MyProject.Droid.Assets.fechar.png"

FromResource is referring to the Android or iOS project not the shared one. The images need to be in the appropriate folder of the platform specific project.

Related

add image in another folder instead of drawable in xamarin cross-platforms

I am able to display image from Drawable folder by using
<image source="live.png"/>
But i don't know how to get image from other folder i create in Resource
Can somebody help me?
Android is very picky about where you can put images, so your best bet is to store your images in the common project. In this example I assume a standard Xamarin.Forms solution with the following projects: Foo, Foo.Android, Foo.IOS and Foo.UWP. Yours will obviously have different names, so you'll have to substitute the Foos...
All the following code will go into the common code project, Foo.
First, create a new folder called Extensions (just to keep your code tidy) and add the following class to it:
[ContentProperty(nameof(Source))]
public class ImageResourceExtension : IMarkupExtension
{
public string Source { get; set; }
public object ProvideValue(IServiceProvider serviceProvider)
{
if (Source == null)
{
return null;
}
var imageSource = ImageSource.FromResource(Source);
return imageSource;
}
}
Now add the namespace for this class to your markup:
xmlns:extensions="clr-namespace:Foo.Extensions"
Next, create a folder for your images, again in your common project, NOT in your Android project. You can create subfolders as well. Add your images and make sure that the build action for each image is set to Embedded Resource.
Now you can reference those images in your XAML like this:
<Image Source="{extensions:ImageResource Foo.Images.Subfolder.Bar.png}">
Note that you need to supply the full path of the image, including the project name (Foo in this case) and that folders are separated by dots, not slashes.

Can Assets/Resoures be shared between iOS + Droid projects?

I have a Xamarin based Visual Studio 2015 project that has the following structure.
MyApp (Portable)
MyApp.Droid
MyApp.iOS
Currently I include assets / resources in the MyApp.Droid project and the MyApp.iOS project.
So for example myhtml.html is duplicated as both MyApp.Droid/Asserts/myhtml.html and MyApp.iOS/Resources/myhtml.html
Are there any ways I can avoid this duplication?
Assuming you are using Xamarin Forms, yes, you can use .net resource files.
You can create a folder in the portable project, add there the content files and set the Compilation Action to Embedded Resource for all of those, then you can use the .net provided mechanism to acces the resources, per example (in this example I assume the code is being executed in a class contained in the portable project and the files are stored in a folder called ResourceFiles):
var htmlFile = this.GetType().GetTypeInfo().Assembly.GetManifestResourceStream("MyNamespace.ResourceFiles.myhtml.html");
In this way you have the stream with the file's content.
Also, as a hint, you can load these files from XAML using a custom markup extension, per example, here is a markup extension to load images from .net resources:
[ContentProperty ("Source")]
public class ImageResourceExtension : IMarkupExtension
{
public string Source { get; set; }
public object ProvideValue (IServiceProvider serviceProvider)
{
if (Source == null)
return null;
var imageSource = new StreamImageSource { Stream = async (ct) => this.GetType().GetTypeInfo().Assembly.GetManifestResourceStream(Source) };
return imageSource;
}
}
Then, to use this extension in XAML you will do (local is the XAML namespace definition of your own namespace):
<Image Source="{local:ImageResource MyNamespace.ResourceFiles.MyImage.png}" />

WPF/XAML: How to reference class that is not defined within any namespace

I'm executing a roslyn script that tries to define and open a WPF window.
Amongst other things, my script
defines an attached behavior
defines a XAML string, based on which I create a WPF Window. In this XAML code, I'd like to use the TextBoxCursorPositionBehavior defined in my script.
my script (.csx) file looks similar to
public class TextBoxCursorPositionBehavior : DependencyObject
{
// see http://stackoverflow.com/questions/28233878/how-to-bind-to-caretindex-aka-curser-position-of-an-textbox
}
public class MyGui
{
public void Show()
{
string xaml = File.ReadAllText(#"GUI_Definition.xaml");
using (var sr = ToStream(xaml))
{
System.Windows.Markup.ParserContext parserContext = new System.Windows.Markup.ParserContext();
parserContext.XmlnsDictionary.Add( "", "http://schemas.microsoft.com/winfx/2006/xaml/presentation" );
parserContext.XmlnsDictionary.Add( "x", "http://schemas.microsoft.com/winfx/2006/xaml" );
parserContext.XmlnsDictionary.Add("i","clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity");
// ?? How can i define this properly?
parserContext.XmlnsDictionary.Add("behaviors", "clr-namespace:;assembly=" + typeof(TextBoxCursorPositionBehavior).Assembly.FullName);
var window = (System.Windows.Window)XamlReader.Load(sr, parserContext);
window.ShowDialog();
}
}
}
and assume the GUI_Definition.xaml looks like
<Window x:Class="System.Windows.Window" Height="300" Width="300" >
<Grid>
<!-- how can i attach my behavior here properly? -->
<TextBox behaviors:TextBoxCursorPositionBehavior.TrackCaretIndex="True"/>
</Grid>
</Window>
But the problem is, how can I reference TextBoxCursorPositionBehavior correctly in XAML?
Roslyn doesn't allow to use namespaces in script files, so TextBoxCursorPositionBehavior must be defined outstide of a namespace (i.e. I suppose it will fall into the global namespace).
But then, how can I reference it in XAML? I've tried defining the namespace reference with "clr-namespace:;assembly=" + typeof(TextBoxCursorPositionBehavior).ToString(), but that doesn't work.
Simply "clr-namespace:" (i.e. without assembly reference) doesn't work either.
Is there any way to reference TextBoxCursorPositionBehavior from within the XAML definition?
In your code instead of assembly you use:
typeof(TextBoxCursorPositionBehavior).ToString()
This is not an assembly name. Change it to:
parserContext.XmlnsDictionary.Add("behaviors", "clr-namespace:;assembly=" + Assembly.GetExecutingAssembly().FullName);
And it should work fine (at least works for me, but I don't test with Roslyn script but just regular WPF application).
I think I know what's happening ... Roslyn creates a custom Submission type for scripts, and seems everything - including the definition of TextBoxCursorPointerBehavior - is a sub-class of this submission type. I.e.,
var inst = new TextBoxCursorPositionBehavior();
string typeName = inst.GetType().FullName;
typeName will not be "TextBoxCursorPointerBehavior", but rather "Submission#0+TextBoxCursorPositionBehavior".
At the same time, I can NOT reference this from XAML (e.g. by behaviors:Submission#0+TextBoxCursorPositionBehavior.TrackCaretIndex="True") as it won't parse the name correctly (# is an invalid token there).
In theory, it might be possible to rename Roslyn's submission type to something that is actually referencable via XAML - in my case though, I cannot do that.
Which unfortunately currently means I don't see any solution to my issue, other than possibly outsourcing this code to a separate pre-compiled DLL (but that's not quite the point of scripting either)

ASP.NET Resource File, Resource Manager for Language Translation

Spending hours on this. Thinking my thought process might be off..
I wanted to create one point of entry for language translation across different libraries and applications.
What I did was the following:
Created New Class Library Project called Translations
At Root Level Added New Item - MyStrings.en-US.resx file
Populated resx file
resx - Access Modifier set to Public
At Root Level of Translations Project Added New Item Class - Translator
Added Property
public class Translator
{
private ResourceManager _translationManager;
public ResourceManager TranslationManager
{
get
{
if (_translationManager == null)
{
_translationManager = new ResourceManager("MyStrings", this.GetType().Assembly);
}
return _translationManager;
}
}
}
In WebSite (not web project but website) Added Reference to Translations Project
In the code behind declared
private Translator _translate;
public Translator Translate
{
get
{
if (_translate == null)
{
_translate = new Translator();
}
return _translate;
}
}
then in a LINQ statement
Title = TranslationManager.GetString(appsAvailable.Value.ResourceKey, CurrentCulture)
ResourceKey does have a value
CurrentCulture = en-US
And I am getting this error
Could not find any resources appropriate for the specified culture or
the neutral culture. Make sure "MyStrings.resources" was correctly
embedded or linked into assembly "Translations" at compile time, or
that all the satellite assemblies required are loadable and fully
signed.
When I look at my bin/obj/debug folder I am seeing this Translations.MyStrings.en-US.resources
which is not the name it is looking for. I have tried to modify the "basename" for the manager from "MyStrings" to 'Translations.MyStrings" but I get a similar error stating "Translations.MyStrings.resources" can't be found. I have also tried just saying okay forget the culture right now let's access it "Translations.MyStrings.en-US" as the base name. and it says it still can not find it.
Any ideas of where I am going wrong? I am thinking it needs to be copied somewhere so the software finds it but don't know where it goes? Or am I trying to do something that it is not meant to do?
Your help is greatly appreciated!
Just download MAT (Multilingual App Toolkit) for Visual Studio. https://marketplace.visualstudio.com/items?itemName=MultilingualAppToolkit.MultilingualAppToolkit-18308
This is the way to go to translate and maintain your projects in Visual Studio ;-)
https://blogs.msdn.microsoft.com/matdev/

Resources Bitmap file - does not contain a definition for Properties

I have the following code skeleton for a Grasshopper component I am making. Grasshopper 3D is a plugin for Rhino 3D, a piece of architecture software. It's a graphical programming language. Anyways, below is a sample Abstract Class, in which I am adding a Bitmap icon to the component.
namespace HM_SettingsForm
{
public class HM_Settings : GH_Component
{
// Misc code
protected override Bitmap Icon
{
get
{
return HM_SettingsForm.Properties.Resources.heatmap;
}
}
// Misc code
}
}
With that said, I am getting the following error.
Here is my Resources folder:
In my case, I was getting the same Error. What I was doing was I had been adding the image to Resources folder. It was adding it, right. but not the definition. So then I double clicked to the Resources.resx in Properties window. (not the resources folder) then I dragged and droped the image into the Resources.resx window. So That image is copied to resources folder and its definition as well .
Hope it helps
Wow I am silly. I overlooked that I used HM_SettingsForm twice.
Simply doing: return Properties.Resources.heatmap; worked.
Got the same problem, resolved it by referencing the Image (in my case a ToolStripMenuImage) from this:
this.tsm.Image = global::ASIM_Formatieren.Properties.Resources.icon_help;
to this
this.tsm.Image = (System.Drawing.Bitmap)Properties.Resources.ResourceManager.GetObject("icon_help");

Categories

Resources