Xamarin.Forms ImageLoaderSourceHandler: Could not retrieve image or image data was invalid - xamarin

Im trying to display an image in xamarin forms from my local ASP.NET API.
I can reach the image on both pc and phone, but not in my custom android application. It also works in UWP.
I get the following error in output window: [0:] ImageLoaderSourceHandler: Could not retrieve image or image data was invalid: Uri: https://192.168.0.207:5001/images/festival/dourfestival.jpg
Im working in xamarin forms 5.0.0.2545
Things i have tried so far:
changing httpclient implementation to Managed
changing ssl/tls implementation to native TLS 1.2+
reinstalling my application
updating xamarin forms to latest stable version
This is my first time posting on here so, if this post lacks some info be sure to let me know, I will edit my post if needed.
XAML
<Image Source="{Binding Image}" Aspect="AspectFill" HeightRequest="270" Opacity="0.6"/>

I solved my issue by adding an URI to imageSource converter, I have used the answer of this post Xamarin Forms - Image source not working from url
Converter
public class ImageSourceURIConverter : IValueConverter
{
static WebClient Client = new WebClient();
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
if (value == null)
return null;
ServicePointManager.ServerCertificateValidationCallback = delegate { return true; };
var byteArray = Client.DownloadData(value.ToString());
return ImageSource.FromStream(() => new MemoryStream(byteArray));
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
XAML
<ContentPage.Resources>
<ResourceDictionary>
<converters:ImageSourceURIConverter x:Key="ImageSourceURIConverter" />
</ResourceDictionary>
</ContentPage.Resources>
<Image Source="{Binding Image, Converter={StaticResource ImageSourceURIConverter}}"
Aspect="AspectFill"
HeightRequest="270"
Opacity="0.6"/>

Related

make label visible in loginpage from viewmodelpage

I log in and set the error label with the isvisible property to false, the problem I have is that I do the control from the viewmodels and therefore, in case of wrong login I have to make the label visible from the viewmodel, someone can help me on how to be able to do?
There are some ways of achieving this using a DataBinding. But you should move your label logic to the ViewModel:
Option A: Controlling the visibility using bool flags
In your viewModel
private bool _isVisible;
public bool IsVisible
{
get => _isVisible;
set {
_isVisible=value;
OnPropertyChanged(nameof(IsVisible));
}
}
And your XAML
<Label x:Name="errorLabel" IsVisible="{Binding IsVisible}"/>
Then you just change the IsVisible inside your login method
Option B: Using converters
This ways uses more code, but the code can be reused. We bind the IsVisible property to an Error String. If the string is empty (no error), then the label will be hidden
Create a converter. This converter will return true if the string is not an error
public class ErrorStringToBool: IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
string errorString = value.ToString();
return !String.IsNullOrEmpty(errorString);
}
....
And declare it in your App.xaml.cs
<ResourceDictionary>
<converters:ErrorStringToBool x:Key="errorStringToBool"/>
....
</ResourceDictionary>
In your Viewmodel declare a string property that is ErrorString. I will skip this code
In your Login.xaml
<Label x:Name="errorLabel" IsVisible="{Binding ErrorString, Converter={x:StaticResource errorStringToBool}}" />

is there any way to set Source for Image From .standard Class Library in UWP

I have create Xamarin Native App only create UI Part platform specfic and shared code(Model,ViewModel) using .net stadard class Library.
In UWP Project I set Source Path Like this
Source="pack://application:,,,/MyClassLibraryName;Component/Assets/AppLogo.png"
It does not work for me!
I have create Xamarin Native App only create UI Part platform specfic and shared code(Model,ViewModel) using .net stadard class Library
For this scenario, you could refer this document that make ImageResourceExtension to load the Embedded image from .net stadard class Library.
We need add the following code to .net stadard class Library.
[Preserve(AllMembers = true)]
[ContentProperty(nameof(Source))]
public class ImageExtension : 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, typeof(ImageExtension).GetTypeInfo().Assembly);
return imageSource;
}
}
Then add image file to .net standard class library and edit the Build Action to Embedded
Usage
ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:mySource="clr-namespace:ImageLib;assembly=ImageLib"
x:Class="WorkingWithImages.EmbeddedImagesXaml">
<StackLayout Margin="20,35,20,20">
<Image Source="{mySource:Image ImageLib.logo.jpg}" />
</StackLayout>
/ContentPage>
Please note: Image path is classlibname.imagename.jpg
Update
You could use uwp uri scheme to add the image path to imgage control, for example
<ImageBrush ImageSource="ms-appx:///Image/AppLogoicon.png" Stretch="UniformToFill" x:Name="Image" />

Xamarin Forms Android Autosize Label TextCompat pre android 8 doesn't autosize text

I want to utilise the auto-sizing feature of android textviews in my xamarin forms solution so that as the text length grows, the font sizes shrinks to never overflow the bounds of the label, and doesn't get truncated. I've created a custom Label control to do so and added an android custom renderer. It's not working in Android 7 and below. It is working in Android 8 and above.
According to the docs autosize support was introduced in android 8, but can be supported back to Android 4 with AppCompat.v4. However, my custom rendered label just renders the default font size in Android pre 8. It works fine in 8+ devices, the label text resizes as needed to not overflow the bounds. The accepted answer to this question with a similar issue on native android says it can be to do with not setting a width and height, I've tried setting widthrequest and heightrequest explicitly and it doesn't change anything. Also setting maxlines=1 doesn't change anything. An alternative thread suggests that custom fonts are the culprit. I created a vanilla forms solution using the default device font, and get the same effect.
My code:
internal class AutosizeLabelRenderer : LabelRenderer
{
#region constructor
public AutosizeLabelRenderer(Context context) : base(context)
{
}
#endregion
#region overridable
protected override void OnElementChanged(ElementChangedEventArgs<Label> e)
{
base.OnElementChanged(e);
if (e.NewElement == null || !(e.NewElement is AutoSizeLabel autoLabel) || Control == null) { return; }
TextViewCompat.SetAutoSizeTextTypeUniformWithConfiguration(Control, autoLabel.AutoSizeMinTextSize,
autoLabel.AutoSizeMaxTextSize, autoLabel.AutoSizeStepGranularity, (int)ComplexUnitType.Sp);
}
#endregion
}
public class AutoSizeLabel : Label
{
public int AutoSizeMaxTextSize
{
get => (int)GetValue(AutoSizeMaxTextSizeProperty);
set => SetValue(AutoSizeMaxTextSizeProperty, value);
}
public static readonly BindableProperty AutoSizeMaxTextSizeProperty = BindableProperty.Create(
nameof(AutoSizeMaxTextSize), // the name of the bindable property
typeof(int), // the bindable property type
typeof(AutoSizeLabel)); // the default value for the property
public int AutoSizeMinTextSize
{
get => (int)GetValue(AutoSizeMinTextSizeProperty);
set => SetValue(AutoSizeMinTextSizeProperty, value);
}
public static readonly BindableProperty AutoSizeMinTextSizeProperty = BindableProperty.Create(
nameof(AutoSizeMinTextSize), // the name of the bindable property
typeof(int), // the bindable property type
typeof(AutoSizeLabel)); // the default value for the property
public int AutoSizeStepGranularity
{
get => (int)GetValue(AutoSizeStepGranularityProperty);
set => SetValue(AutoSizeStepGranularityProperty, value);
}
public static readonly BindableProperty AutoSizeStepGranularityProperty = BindableProperty.Create(
nameof(AutoSizeStepGranularity), // the name of the bindable property
typeof(int), // the bindable property type
typeof(AutoSizeLabel)); // the default value for the property
//
}
Not working: Android 7 - text does not shrink
Working as expected: Android 8 and above
Xaml for above images:
<StackLayout HeightRequest="200" WidthRequest="100">
<Label Text="Fixed width and height, sentences get longer, text should shrink" />
<controls:AutoSizeLabel
AutoSizeMaxTextSize="50"
AutoSizeMinTextSize="8"
AutoSizeStepGranularity="1"
BackgroundColor="{StaticResource Shamrock}"
HeightRequest="40"
HorizontalOptions="Start"
MaxLines="1"
Text="A small sentence"
WidthRequest="200" />
<controls:AutoSizeLabel
AutoSizeMaxTextSize="50"
AutoSizeMinTextSize="8"
AutoSizeStepGranularity="1"
BackgroundColor="{StaticResource Shamrock}"
HeightRequest="40"
HorizontalOptions="Start"
MaxLines="1"
Text="A larger sentence that shrinks"
WidthRequest="200" />
<controls:AutoSizeLabel
AutoSizeMaxTextSize="50"
AutoSizeMinTextSize="8"
AutoSizeStepGranularity="1"
BackgroundColor="{StaticResource Shamrock}"
HeightRequest="40"
HorizontalOptions="Start"
MaxLines="1"
Text="An even larger sentence that shrinks more."
WidthRequest="200" />
</StackLayout>
TextView font size changes with the size of the control, which is new in Android 8.0 (API26),therefore, compatibility issues need to be considered when using the previous version.You could change the TextView to AppCompatTextView.
Change your
protected override void OnElementChanged(ElementChangedEventArgs<Label> e)
{
base.OnElementChanged(e);
if (e.NewElement == null || !(e.NewElement is AutoSizeLabel autoLabel) || Control == null) { return; }
AppCompatTextView appCompatTextView = new AppCompatTextView(_context);
appCompatTextView.Text = Element.Text;
appCompatTextView.SetMaxLines(1);
SetNativeControl(appCompatTextView);
TextViewCompat.SetAutoSizeTextTypeUniformWithConfiguration(Control,autoLabel.AutoSizeMinTextSize,autoLabel.AutoSizeMaxTextSize, autoLabel.AutoSizeStepGranularity, (int)ComplexUnitType.Sp);
}
Leo Zhu's answer got me most of the way there. There were a couple of extra steps I needed to take to get it fully working, so I'm posting the code as a separate answer here.
Differences between mine and Leo's answer:
Creating a new native control in scope like Leo suggested meant that it worked for a while but got disposed by the garbage collector and caused an exception when returning to the page after navigating away. To fix this I needed to override a property called ManageNativeControlLifetime to return false, and then manually manage disposing the object by overriding the dispose method and calling Control.RemoveFromParent();. This advice comes from a xamarin staff member in this thread.
Formatting and binding context are not automatically inherited when creating the new native control and need to be set manually. I needed to add those based on my needs using the android specific binding syntax. You may need to add other formatting and binding code based on your needs, I'm just doing font colour, gravity and binding context here.
I set the binding context with
appCompatTextView.SetBindingContext(autoLabel.BindingContext);
Once the binding context was set, I needed to add a new string property to my XF AutoSizeLabel class to pass in through XAML, then use it to set the binding path for the relevant property (In my case the text property). If more than one binding is required, you would need to add multiple new binding path properties for each required property. I set a specific binding like this:
appCompatTextView.SetBinding("Text", new Binding(autoLabel.TextBindingPath));
To facilitate this in my Xamarin Forms Xaml, my Xaml went from <Label Text="{Binding MyViewModelPropertyName}" /> to <controls:AutoSizeLabel TextBindingPath="MyViewModelPropertyName" />
Here's the full code of the renderer:
protected override bool ManageNativeControlLifetime => false;
protected override void Dispose(bool disposing)
{
Control.RemoveFromParent();
base.Dispose(disposing);
}
private AppCompatTextView appCompatTextView;
protected override void OnElementChanged(ElementChangedEventArgs<Label> e)
{
base.OnElementChanged(e);
if (e.NewElement == null || !(e.NewElement is AutoSizeLabel autoLabel) || Control == null) { return; }
//v8 and above supported natively, no need for the extra stuff below.
if (DeviceInfo.Version.Major >= 8)
{
Control?.SetAutoSizeTextTypeUniformWithConfiguration(
autoLabel.AutoSizeMinTextSize,
autoLabel.AutoSizeMaxTextSize, autoLabel.AutoSizeStepGranularity,
(int)ComplexUnitType.Sp);
return;
}
appCompatTextView = new AppCompatTextView(Context);
appCompatTextView.SetTextColor(Element.TextColor.ToAndroid());
appCompatTextView.SetMaxLines(1);
appCompatTextView.Gravity = GravityFlags.Center;
appCompatTextView.SetBindingContext(autoLabel.BindingContext);
appCompatTextView.SetBinding("Text", new Binding(autoLabel.TextBindingPath));
SetNativeControl(appCompatTextView);
TextViewCompat.SetAutoSizeTextTypeUniformWithConfiguration(Control, autoLabel.AutoSizeMinTextSize, autoLabel.AutoSizeMaxTextSize, autoLabel.AutoSizeStepGranularity, (int)ComplexUnitType.Sp);
}

How to set an image from Embedded resource using XAML in Xamarin.Forms

When setting an image source in code and pointing towards an embedded image in a specific folder in the PCL project ('Images' in this instance) I would do this:
backgroundImg.Source = ImageSource.FromResource("Myapp.Images." + imageName + ".jpg");
Is there a way to do this in XAML?
#Code Pope is correct in his answer, but you also need to add an "ImageResourceExtension" as noted in the comments by #Gerald Versluis.
To do that just create a new file (class) "ImageResourceExtension.cs" like this:
using System;
using System.Reflection;
using Xamarin.Forms;
using Xamarin.Forms.Xaml;
namespace ImageResourceExtension
{
[ContentProperty (nameof(Source))]
class ImageResourceExtension : IMarkupExtension
{
public string Source { get; set; }
public object ProvideValue(IServiceProvider serviceProvider)
{
if (Source == null)
{
return null;
}
var imageSource = ImageSource.FromResource(Source, typeof(ImageResourceExtension).GetTypeInfo().Assembly);
return imageSource;
}
}
}
Then add xmlns:local="clr-namespace:ImageResourceExtension" to your xaml file like this:
<ContentPage 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"
xmlns:local="clr-namespace:ImageResourceExtension"
...
Now you can access an embedded resource using xaml code like this:
<Image Source="{local:ImageResource MyProject.Resources.Images.Logo.png}" />
Use the following code:
<Image Source="{local:ImageResource YourMobileAppName.YouImageName.jpg}" />
For more info, read here
I managed to get this working by adding the ImageSource as an object in my View Model
public object ImageSource { get; set; }
Then populating the View Model as follows:
ImageSource = Xamarin.Forms.ImageSource.FromResource("ProjectName.Resources.Images.Image1.png", typeof(WalkthroughViewModel).GetTypeInfo().Assembly),
In the XAML, I simply referenced it as I would any other binding.
<Image Source="{Binding ImageSource}"/>
I am aware that the question doesn't necessarily use/require model-binding as you would with MVVM but I stumbled upon the answer provided above which helped me figure out the MVVM approach for anyone else who finds it useful. My particular use-case was for a CarouselView where I figured an embedded set of images would be useful.
you can set image from xaml like <Image Source="imageName" Aspect="AspectFit" />
Make sure your image available in iOS Resources and in Android Resources -> drawable

WP7 LonglistSelector databinding - How to trigger an update to a bound item's binding

The longlistselector control appears to be just what I need for my application as I have a very long list that I need to display and I like the grouping features that it implements, but I'm really struggling with the databinding aspect of working with it. It took a while to get the basic databinding working, but I have that fully functional. If an item is removed or added the UI updates properly because the datasource derives from ObservableCollection.
The problem that I am having is that I have a flag in the individual dataitems that I am binding to that indicates if an individual list item should display or hide a graphic. The idea is that when the user performs a hold gesture on an item it will toggle the graphic on or off based on changes to the bound item's properties.
Visibility="{Binding Converter={StaticResource isFavoriteToVisibility}}
The LongListSelector databinding requirements for getting the group headers and such requires a datasource like ObservableCollection<ObservableCollection<MyItem>> (which is confusing just to look at!). Essentially, the outer collection is the Groups and the the inner collection contains the displayed items. My items even implement the INotifyPropertyChanged interface. What I'd expected was for updates to my item's properties to be automatically reflected in my databinding, not just the addition or removal of items from the collection.
If I toggle the property value nothing whatsoever happens until I manually refresh the binding which requires a full reload. It is possible that this control doesn't respond the propertychanged events of the individual items.
What I need is help figuring out what I can do to trigger an update of an individual list item after I have changed a property of it's bound object?
Update:
Claus, the code that you created was VERY helpful (sorry, I don't have enough rep to vote you up yet!) Using that code I was able to significantly simplify my code, and do more tests, but it still doesn't solve my problem.
What I've now determined is that my binding is fine. If I change the property when bound simply to a text field text="{Binding IsFavorite}" it updates flawlessly. What doesn't seem to work is when I update that same property when bound to the IValueConverter Visibility="{Binding Converter={StaticResource isFavoriteToVisibility}}" it doesn't update. The converter works fine at initial binding, but not on property change. To go farther with testing, I bound the same bool property to both a text field and the IValueConverter. When I change the bool value the text field updates, but not the field bound using the converter.
public class VisibilityConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
Chemical chem = value as Chemical;
if (chem == null)
return Visibility.Collapsed;
if (chem.IsFavorite)
return Visibility.Visible;
else
return Visibility.Collapsed;
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
throw new NotImplementedException();
}
}
XAML:
<myNS:ChemicalToFavoriteVisibilityConverter x:Key="isFavoriteToVisibility" />
<Rectangle Grid.Column="0"
Fill="{StaticResource PhoneContrastBackgroundBrush}"
Height="26" Stroke="Black" Width="26"
Visibility="{Binding Converter={StaticResource isFavoriteToVisibility}}">
<Rectangle.OpacityMask>
<ImageBrush ImageSource="/Images/star_big.png"/>
</Rectangle.OpacityMask>
</Rectangle>
<StackPanel Grid.Column="1" Margin="0,0,0,0">
<TextBlock Text="{Binding IsFavorite}"
TextWrapping="Wrap"
Style="{StaticResource PhoneTextLargeStyle}"
Foreground="{StaticResource PhoneForegroundBrush}"/>
</StackPanel>
I solved the problem. The problem was that I was passing the entire object to the IValueConverter instead of the specific property that changed within the object. I changed the converter to specifically handle conversion of bool to Visibility and fixed the binding:
public class BoolToVisibilityConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
bool boolValue = (bool)value;
return boolValue ? Visibility.Visible : Visibility.Collapsed;
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
throw new NotImplementedException();
}
}
The binding changed from:
Visibility="{Binding Converter={StaticResource isFavoriteToVisibility}}"
to:
Visibility="{Binding Converter={StaticResource isFavoriteToVisibility}, Path=IsFavorite}"
Can you verify that in your binding you are not using OneTime as the Binding Mode (instead of OneWay)?
I've used data binding without problems in items in a list bound to the LongListSelector - I suspect that the issue won't lie with the LongListSelector, but with your binding or your INotifyPropertyChanged ... can you post some code (ideally the binding, and also the objects being bound).

Resources