Embedded image does not show in Xamarin Android App - c#

I follow the guide on the official Xamarin website telling how to embed the image into the cross-platform app. I build the app only for Android platform.
Unfortunately, the image is not shown during debug on my Sony D5803 Z3 Compact or in Android 7.1 emulator. I use VS 2017 RC on Windows 10. All the previous HelloWorld apps e.g. with downloading the picture via URI worked well on my phone.
I would be grateful for any help or advice how to troubleshoot the problem.
The image picture.jpg has set the build property embedded resource (in Polish Akcja kompilacji: osadzony zasób)
I can see the images in the debug folder as shown in the screenshot
This is the XAML page I use to show the image:
ImageEmbeddedPAge.xaml
<?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:markupExtensions="clr-namespace:HelloWorld.MarkupExtensions;assembly=HelloWorld.Droid"
x:Class="HelloWorld.ImageEmbeddedPAge">
<StackLayout HorizontalOptions="Center"
VerticalOptions="Center">
<Image x:Name="image"
Source="{markupExtensions:ImageResource Source=HelloWorld.Images.picture.jpg}"/>
</StackLayout>
</ContentPage>
ImageResourceExtension.cs in folder MarkupExtensions
namespace HelloWorld.MarkupExtensions
{
[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;
}
}
}
App.xaml.cs
namespace HelloWorld
{
public partial class App : Application
{
public App ()
{
InitializeComponent();
MainPage = new ImageEmbeddedPAge();
}
}
}

Totally agree with #Cheesebaron, since you created a Xamarin.Forms shared projecrt, we need to place resolution images in specially-named directories in Android project, these specially-named directories are all placed under the Resources-> Drawable folder in the Android project.
If you want to use an embedded image, we need to use a Portable Lib for each platfrom, or just create a Xamarin.Forms portable project. If you want to create a PCL by yourself, than please be careful with the targets of this PCL, normally it should be like following image so can it be used for different platforms:
And finally to embed an image in a project, by default the image will have Build Action: None, please set it to Build Action: EmbeddedResource.
The reason why we cannot place images in a shared project is that:
The shared project reference shows up under the References node in the Solution Explorer, but the code and assets in the shared project are treated as if they were files linked into the main project.
The images then are treated as files not resources.

Related

How to distribute my WebView2 WPF app by Fixed Version distribution mode?

I want to distribute my wpf app with fixed version WebView2, here is my XAML code:
XAML:
<wv2:WebView2 x:Name="webView" vm:ReceiverViewModel.PreviewData="{Binding MyData}">
<wv2:WebView2.CreationProperties>
<wv2:CoreWebView2CreationProperties>
<wv2:CoreWebView2CreationProperties.BrowserExecutableFolder>
Microsoft.WebView2.FixedVersionRuntime.87.0.664.8.x86\\EBWebView\\x86
</wv2:CoreWebView2CreationProperties.BrowserExecutableFolder>
</wv2:CoreWebView2CreationProperties>
</wv2:WebView2.CreationProperties>
</wv2:WebView2>
C#:
public Receiver()
{
InitializeComponent();
webView.Source = new Uri(System.IO.Directory.GetCurrentDirectory() + "/Receiver.html");
}
It doesn't work. Is BrowserExecutableFolder set correctly?
For Fixed Version deployment, when providing a browserExecutableFolder you must specify the path to the folder containing msedgewebview.exe. In the above you likely want to specify Microsoft.WebView2.FixedVersionRuntime.87.0.664.8.x86 not the EBWebView\x86 subfolder.

Determine if library loaded into Console, Desktop, or UWP app

I have a libary which needs to behave differently for console applications, desktop application (e.g. WPF), and for UWP apps.
How can I determine at run-time into which application type my libary is loaded?
Determining if it is a console application seems easy: How to tell if there is a console
For UWP, I can probably determine if WinRT is loaded. But how?
What distinguishing attributes do desktop applications have?
I ended up defining following enum:
public enum ExecutionMode
{
Console,
Desktop,
UniversalWindowsPlatform
}
which is passed to the constructor of the main class of my libary. Not a new idea, but very reliable (if used correctly).
Create a CustomAttribute in an assembly that is available to all of the applications like so
using System;
namespace MyNamespace.Reflection {
[System.AttributeUsage(AttributeTargets.Assembly)]
public class ApplicationTypeAttribute : Attribute {
public enum ApplicationTypes {
Console,
Desktop,
UWP,
ClassLibrary
}
public ApplicationTypeAttribute(ApplicationTypes appType) {
ApplicationType = appType;
}
public ApplicationTypes ApplicationType { get; private set; } = ApplicationTypes.Console;
}
}
Then add this attribute to your AssemblyInfo.cs file for a console application
using MyNamespace.Reflection;
[assembly: ApplicationType(ApplicationTypeAttribute.ApplicationTypes.Console)]
or a Desktop application
[assembly: ApplicationType(ApplicationTypeAttribute.ApplicationTypes.Desktop)]
etc.
Then wherever you want to check the calling type of the application that was started, use this
using MyNamespace.Reflection;
var assy = System.Relection.Assembly.GetEntryAssembly();
var typeAttribute = assy.GetCustomAttribute(typeof(ApplicationTypeAttribute));
if (typeAttribute != null) {
var appType = ((ApplicationTypeAttribute)typeAttribute).ApplicationType;
}
There is one caveat to this method. .NET Core apps have a different project structure and the AssemblyInfo.cs file is auto-generated at build time by default. You can override this behavior by specifying the following in the .csproj file in the Project node.
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
To match the old project file structure, you can create a Properties directory in the project directtory and then you can add an AssemblyInfo.cs file to that directory. Otherwise you can place the Custom Attribute definition in any file (after the usings and before the namespace declaration).

Xamarin XAML: Type is not found from external assembly

I have a Visual Studio solution, which has 2 C# projects:
a C# portable BasicLib;
a C# portable XAML project.
I defined resource files and a public LocalizedStrings class in the BasicLib. Its namespace is "PL.Common.BasicLib", the assembly name is "PL.Common.BasicLib.dll".
LocalizedStrings.cs
namespace PL.Common.BasicLib
{
/// <summary>
/// Provides access to string resources.
/// </summary>
public class LocalizedStrings
{
private static AppResources _localizedResources = new AppResources();
public AppResources LocalizedResources { get { return _localizedResources; } }
}
}
Then I add reference from the XAML project to this PL.Common.BasicLib. So far so good. I double click the assembly name from the XAML project's "References" node, I can see the Type "LocalizedStrings" under the "PL.Common.BasicLib" in the Visual Studio's "Object Browser".
Now, I would like to put this resource into App.xaml as application resource in this way:
App.xaml:
<?xml version="1.0" encoding="utf-8" ?>
<Application xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:basiclib="clr-namespace:PL.Common.BasicLib;assembly=PL.Common.BasicLib"
x:Class="PL.Common.Xaml.App">
<Application.Resources>
<basiclib:LocalizedStrings x:Key="LocalizedStrings"/>
</Application.Resources>
</Application>
Build the solution, no problem. When running it, there will throw an error:
Xamarin.Forms.Xaml.XamlParseException: Position 8:6.
Type basiclib:LocalizedStrings not found in xmlns clr-namespace:PL.Common.BasicLib;assembly=PL.Common.BasicLib
Can someone help to take a look where is the bug?
thanks!
This could be related to a known linking issue - where Xamarin compiler ends up linking out classes (from external assemblies) that have references only in XAML.
There are couple of links that talk about this:
Extending Control plugins > Getting Started
Force assembly linking
There are a lot of options to resolve this:
Add a static Init method in each class as mentioned here in "Getting started" section here
// this ensures the class does not get
// linked out in the application we add this assembly to.
public static void Init() { }
Or, preserve code using preserve attributes on Android, and iOS
public class Example
{
[Android.Runtime.Preserve]
public Example ()
{
}
}
Or, use Custom linking.
Or, update project configuration to not link. Android, and iOS. Not a recommended option though.

Evaluate project full path in XAML designer (XDesProc.exe)

I have UserControl displaying file information. And I want to see test file information in visual studio designer using view-model mock. Here is XAML:
<Label Content="{Binding DateCreated}"/>
View-model:
internal class ViewModel
{
public ViewModel(string pathToFile)
{
var file = new FileInfo(pathToFile);
this.DateCreated= file.CreationTime.ToShortDateString();
}
public string DateCreated{ get; set; }
}
In design-time I see real file information in designer using view-model mock class:
internal class ViewModelMock : ViewModel
{
public ViewModelMock() : base(#"D:\Images\mock.png")
{
}
}
I plug mock into xaml via d:DataContext and d:DesignInstance:
<UserControl ...
xmlns:mocks="clr-namespace:Company.Product.Mocks"
d:DataContext="{d:DesignInstance mocks:ViewModelMock, DesignTimeCreatable=True}">
It works, but the problem is in this #"D:\Images\mock.png" hardcoded value. As soon as solution powered by TFS, I need to place the image into the project and reference this image from ViewModelMock, relative to project path.
How can I do that?
Simple methods like getting current working directory gives 'C:\Program Files (x86)\Microsoft Visual Studio 12.0\Common7\IDE', I guess because this is location of XDesProc.exe which responsible for visual studio designer.
Currently I'm using EnvDTE method described in this questions:
var solutionFullName = ((EnvDTE.DTE)System.Runtime.InteropServices.Marshal.GetActiveObject("VisualStudio.DTE.12.0")).Solution.FullName;
var projectPath = Path.Combine(Path.GetDirectoryName(solutionFullName), "ProjectFolderName");
But this has almost the same problem - hardcoded "VisualStudio.DTE.12.0" constant (which means Visual Studio 2013), so I'm still trying to find better solution.

Call the Resource name for TextBlock control in Windows Store App

i am new to Windows store app. now i created the folder for the resource file for French[Strings -> fr-FR ->Resources.resw] and English[Strings -> en-US ->Resources.resw].
and declared the Heading1="hdFREN" and Heading1="hdENG" respectively.
now i have to call the Heading1 to the TextBlock text="".. How to declare the text in the TextBlock control???
Actually i created the resources.resw in the root folder [Strings -> fr-FR ->Resources.resw] and English[Strings -> en-US ->Resources.resw]. then i am creating manually LocalizedStrings
enter code here
public class LocalizedStrings
{
private static Resources _localizedResources = new Resources();
public Resources LocalizedResources { get { return _localizedResources; } }
}
now i can't call that Resources file. it is showing error
This is a an overview of localization, and should address most of your questions.
Quickstart: Translating UI resources (Windows Store apps using C#/VB/C++ and XAML)

Categories