ImageCell not displaying image only on Android - xamarin

I've been trying to get an ImageCell to show an image in a very basic ListView for some time now using the Shared library. The problem ONLY appears on Android, the iOS version is working as intended.
PS: I am having issues loading images from the internet as well, again only for Android. I'm certain the problem is the same. I have already added the Internet permission in the manifest, and have tried all of the different HttpClientImplementation and SSL/TLS implementation options.
My XAML is as follows:
<?xml version="1.0" encoding="UTF-8"?>
<ContentPage
xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="TestXamarin.GreetPage">
<ListView x:Name="listView">
<ListView.ItemTemplate>
<DataTemplate>
<ImageCell Text="{Binding Name}" Detail="{Binding Status}" ImageSource="{Binding ImageUrl}" />
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</ContentPage>
The code behind class is like this :
public partial class GreetPage : ContentPage
{
public GreetPage()
{
On<iOS>().SetUseSafeArea(true);
InitializeComponent();
listView.ItemsSource = new List<Contact>
{
new Contact { Name="John", ImageUrl = "http://lorempixel.com/100/100/people/1" },
new Contact { Name="Jack", ImageUrl = "http://lorempixel.com/100/100/people/2", Status="Hello guys" },
new Contact { Name="Jill", ImageUrl = "http://lorempixel.com/100/100/people/3" }
};
}
}
The Contact.cs class is this:
public class Contact
{
public string Name { get; set; }
public string Status { get; set; }
public string ImageUrl { get; set; }
}

Your issue is related with the restrictions on later Android versions with non secure (http) connections.
If you debug the app and look at the Output you will see a message like this:
Image Loading: Error getting stream for
http://lorempixel.com/100/100/people/1: Java.IO.IOException: Cleartext
HTTP traffic to lorempixel.com not permitted at
Java.Interop.JniEnvironment+InstanceMethods.CallVoidMethod
(Java.Interop.JniObjectReference instance, Java.Interop.JniMethodInfo
method, Java.Interop.JniArgumentValue* args) [0x00069] in
:0 at
Java.Interop.JniPeerMembers+JniInstanceMethods.InvokeAbstractVoidMethod
(System.String encodedMember, Java.Interop.IJavaPeerable self,
Java.Interop.JniArgumentValue* parameters) [0x00014] in
:0 at
Java.Net.HttpURLConnectionInvoker.Connect () [0x0000a] in
:0 at
Xamarin.Android.Net.AndroidClientHandler+<>c__DisplayClass44_0.b__0
() [0x0005a] in :0 at
System.Threading.Tasks.Task.InnerInvoke () [0x0000f] in
:0 at
System.Threading.Tasks.Task.Execute () [0x00000] in
:0
--- End of stack trace from previous location where exception was thrown ---
As you can read there a message saying Cleartext HTTP traffic to lorempixel.com not permitted at
The quickest solution is to add the android:usesCleartextTraffic="true" at the application level in the Manifest.xml file:
<application android:label="MyApp.Android" android:usesCleartextTraffic="true">
...
</application>
But the above is not the recomended as it open a breach in terms of security. The best solution would be to use https in your Urls.
Hope this helps

Related

System.TypeLoadException occurred in Microsoft.Xaml.Interactivity

I am trying to attach an event handler in ListView with Microsoft.Xaml.Interactivity in my UWP application. When I select a row in ListView, the application executes a procedure according to the selected item.
So, I've installed the "Microsoft.Xaml.Behaviors.Uwp.Managed" package and changed a XAML file like this:
<ListView VerticalAlignment="Stretch"
x:Name="listBoxobj"
HorizontalAlignment="Stretch"
Margin="10,0,0,10"
Background="White"
Foreground="Black"
ScrollViewer.HorizontalScrollBarVisibility="Disabled"
ItemsSource="{Binding Tools}"
SelectedItem= "{Binding SelectedItem, Mode=Twoway}"
SelectionMode="Single">
<Interactivity:Interaction.Behaviors>
<Interactions:EventTriggerBehavior EventName="ItemClick" SourceObject="listBoxObj">
<Interactions:InvokeCommandAction Command="{Binding Tool_Clicked}" CommandParameter="{Binding SelectedItem}" />
</Interactions:EventTriggerBehavior>
</Interactivity:Interaction.Behaviors>
And the following has been implemented in its ViewModel:
private System.Windows.Input.ICommand tool_Clicked;
public ICommand Tool_Clicked
{
get {
return tool_Clicked;
}
set {
if (!Object.ReferenceEquals(tool_Clicked, value))
{
tool_Clicked = value as RelayCommand;
OnPropertyChanged("Tool_Clicked");
}
}
}
public DisplayViewModel()
{
...
Tool_Clicked = new RelayCommand(SelectionChanged);
...
}
public void SelectionChanged(object arg) {
... executes some procedures according to the selected item...
}
But when I tested these codes, the following exception has emitted:
System.TypeLoadException: 'Could not find Windows Runtime type 'System.Windows.Input.ICommand'.'
In Debug mode, on the other hand, no such exception has been thrown.
So, I have two questions:
I wonder what is the difference betweeen the Debug mode and the Release mode.
Are there any way to avoid throwing the System.TypeLoadException?
Update 1:
I have configured the compile options at Release mode.
I've checked "Compile with .NET native tool chain"
I've checked "unsafe code".
But when I tried to build my project, it has ended with the following error message:
error : MCG0018:TypeExpected Type File or assembly 'System.Runtime.InteropServices.WindowsRuntime.PropertyType' not found.
When I tried unchecking "Compile with .NET native tool chain", I could run this code. I think some of the nuget packages I use don't support .NET native code...
Update 2:
I've made the RelayCommand class like the following:
public class RelayCommand : ICommand
{
private readonly Action<Object> _execute;
private readonly Func<object, bool> _canExecute;
public event EventHandler CanExecuteChanged;
public RelayCommand(Action<object> execute) :
this(execute, null)
{ }
public RelayCommand(Action<object> execute, Func<object, bool> canExecute)
{
_execute = execute ?? throw new ArgumentNullException("execute");
_canExecute = canExecute;
}
public bool CanExecute(object parameter)
{
return _canExecute == null ? true : _canExecute(parameter);
}
public void Execute(object parameter)
{
_execute(parameter);
}
public void RaiseCanExecuteChanged()
{
CanExecuteChanged?.Invoke(this, EventArgs.Empty);
}
}
I noticed that your question has been solved on Microsoft Q&A-System.TypeLoadException occurs in the Release Mode by Nico.
To make Nico's answer short, you could use the Tapped event instead of using the click event. Then you could use the current datacontext as parameter
Code like this:
<DataTemplate>
<TextBlock Text="{Binding}">
<Interactivity:Interaction.Behaviors>
<Interactions:EventTriggerBehavior EventName="Tapped">
<Interactions:InvokeCommandAction Command="{Binding ElementName=listBoxObj, Path=DataContext.Tool_Clicked}" CommandParameter="{Binding}" />
</Interactions:EventTriggerBehavior>
</Interactivity:Interaction.Behaviors>
</TextBlock>
</DataTemplate>

Login to ASP.Net application from Xamarin using Authentication token

I am trying to login to my ASP.net application from xamarin using authentication token.
Here is my LoginViewModel.cs
public class LoginViewModel : ContentPage
{
private ApiServices _apiServices = new ApiServices();
public string Username { get; set; }
public string Password { get; set; }
public ICommand LoginCommand
{
get
{
return new Command(async() =>
{
var isLogin = await _apiServices.LoginAsync(Username, Password);
if (isLogin)
{
await Navigation.PushModalAsync(new Dashboard());
}
});
}
}
}
The var isLogin is returning true but the application is not navigating to Dashboard page
Here is my LoginAsync function
public async Task<bool> LoginAsync(string userName, string password)
{
var keyValues = new List<KeyValuePair<string, string>>
{
new KeyValuePair<string, string>("username",userName),
new KeyValuePair<string, string>("password",password),
new KeyValuePair<string, string>("grant_type","password"),
};
var request = new HttpRequestMessage(HttpMethod.Post, "http://epolleasy.azurewebsites.net/Token");
request.Content = new FormUrlEncodedContent(keyValues);
var client = new HttpClient();
var response = await client.SendAsync(request);
var jwt = await response.Content.ReadAsStringAsync();
JObject jwtDynamic = JsonConvert.DeserializeObject<dynamic>(jwt);
var accessToken = jwtDynamic.Value<string>("access_token"); //variable for acsess_token
//Debug.WriteLine(jwt);
if (!string.IsNullOrEmpty(accessToken))
{
return response.IsSuccessStatusCode;
}
else
{
return response.IsSuccessStatusCode;
}
}
From the looks of the code you have, the problem looks like a simple misunderstanding of how things work.
First it appears you are trying to implement your own MVVM pattern which is fine, except ViewModels aren't pages. Your code shows that you are trying to make your ViewModel a ContentPage. My only guess is that it's so you can access things like Navigation, Alerts and ActionSheets.
If you're implementing your own basic MVVM it may be necessary to make some sacrifices to make things work. In Xamarin Forms, things like Navigation in particular generally requires an understanding of where you want to navigate from. As a basic sample consider the follow where we want to navigate from ViewA to ViewB
ViewAViewModel.cs
public class ViewAViewModel
{
private Page _page { get; }
public ViewAViewModel(Page page)
{
_page = page;
NavigateCommand = new Command(OnNavigateCommandExecuted);
}
public Command NavigateCommand { get; }
private void OnNavigateCommandExecuted() =>
_page.Navigation.PushModalAsync(new ViewB());
}
You'll notice that my ViewModel in this case accepts a Page so that it can properly navigate from the Page the ViewModel is used on. Because this is such a basic example and everything is set in the constructor, you'll notice this ViewModel doesn't need to inherit from any other class, nor does it even implement INotifyPropertyChanged. Your ViewModels in a real application would likely need to at least implement INotifyPropertyChanged.
ViewA.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"
x:Class="BasicMvvm.Views.ViewA">
<Button Text="Navigate"
HorizontalOptions="Center"
VerticalOptions="Center"
Command="{Binding NavigateCommand}" />
</ContentPage>
ViewA.xaml.cs
public partial class ViewA : ContentPage
{
public ViewA()
{
InitializeComponent();
BindingContext = new ViewAViewModel(this);
}
}
Now that said you really are better off using an actual MVVM framework. I would suggest that you take a look at Prism as it will nicely abstract everything away and keep your code nice and testable.

Silent exception when binding PivotItem header

I've noticed a strange exception in my Windows Phone 7.1 application that really made me crazy.
These are the facts...
I start defining a simple Pivot item with two simple PivotItem inside:
<Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
<controls:Pivot>
<controls:PivotItem x:Name="PivotItem1"
Header="Test1" />
<controls:PivotItem x:Name="PivotItem2"
Header="{Binding Path=Text2, Mode=OneWay}" />
</controls:Pivot>
<Button Content="Test" Click="Button_Click" />
</Grid>
And this is my code-behind...
EDIT: As Gambit suggested me, I will show you more code.
In the real situation, I DO HAVE A MVVM, but in this case I simplified the situation to let you reproduce the problem in an easy way...
For this test the next is my View:
public partial class MainPage : PhoneApplicationPage, INotifyPropertyChanged
{
private string _text2 = "<Missing>";
public string Text2
{
get
{
return _text2;
}
private set
{
_text2 = value;
NotifyPropertyChanged("Text2");
}
}
public MainPage()
{
InitializeComponent();
}
private void PhoneApplicationPage_Loaded(object sender, RoutedEventArgs e)
{
this.DataContext = this;
}
public event PropertyChangedEventHandler PropertyChanged;
public void NotifyPropertyChanged(string propertyName)
{
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
private void Button_Click(object sender, RoutedEventArgs e)
{
this.Text2 = "Second page";
}
}
So, it's not just the parameter initialization of a NULL value: you will see the exception.
Obviously, you are asking me for the controls namespace declaration. This is:
xmlns:controls="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone.Controls"
This refers to the assembly Microsoft.Phone.Controls.dll, version 2.0.50727.
My problem is related to the binding (as I discovered investigating the problem):
Header="{Binding Path=Text2, Mode=OneWay}"
If you do not use bindings linked to the Header property of the PivotItem, everything works well, otherwise...the app will throw an exception, completely silent, and it won't show up in any case (you can see the exception only in the Output Window):
A first chance exception of type 'System.Exception' occurred in System.Windows.dll
If you assign the Header property manually, no exceptions will be thrown.
I want to completely remove this exceptions, because I have a lot of bindings to the Header property, I don't want to break my MVVM...and it's also very annoying!
I really hate to see unmanaged exceptions...
Does anyone know about this problem?
Any solution/workaround?
Any help will be very appreciated...thank you!
Based on the code provided, I would suspect that the issue is the DataContext is not being set. In your example, the DataContext is set in the PhoneApplicationPage_Loaded event. However, it doesn't appear that you are registering for this event anywhere. In the constructor of MainPage, add a line like:
this.Loaded += new RoutedEventHandler(PhoneApplicationPage_Loaded);

how to Show data on a web browser control?

I wants to show simple string in web browser.And as per bellow code when i am run application it will not show any string and not give error.
so how can i show string or html cantent in web broser controll.
XMl Code is
<Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
<phone:WebBrowser HorizontalAlignment="Left" Margin="9,6,0,0" Name="webBrowser1" VerticalAlignment="Top" Width="441" Height="595" Foreground="Black" />
</Grid>
My C# cod is:
public Page2()
{
InitializeComponent();
webBrowser1.Loaded += WebBrowser_OnLoaded;
}
private void WebBrowser_OnLoaded(object sender, RoutedEventArgs e)
{
//<html><head><meta name='viewport' content='width=480, user-scalable=yes' /></head><body><h2>Welcome to F5debug!</h2><p>To get more updates visit www.f5Debug.net</p></body></html>
webBrowser1.NavigateToString("hello");
}
public Page2() {
{
InitializeComponent();
webBrowser1.NavigateToString("hello");
}
}
Is this ok?

Localizing Silverlight application using resources

I have a problem with localization of Silverlight application using resources. I wanted to make my multilingual mechanizm to be cross platform thats why I placed all localizable resources in project of type Portable Class Library.
In this project I created two resource files
Localization.resx and Localization.en.resx and I set and "access modifier" to public in both files. Then I created the proxy class called "LocalizationProxy" which is a proxy class to enable bindings.
public class LocalizationProxy : INotifyPropertyChanged
{
public Localization LocalizationManager { get; private set; }
public LocalizationProxy()
{
LocalizationManager = new Localization();
}
public void ResetResources()
{
OnPropertyChanged(() => LocalizationManager);
}
#region INotifyPropertyChanged region
public event PropertyChangedEventHandler PropertyChanged;
public void OnPropertyChanged<T>(Expression<Func<T>> selector)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(GetPropertyNameFromExpression(selector)));
}
}
public static string GetPropertyNameFromExpression<T>(Expression<Func<T>> property)
{
var lambda = (LambdaExpression)property;
MemberExpression memberExpression;
if (lambda.Body is UnaryExpression)
{
var unaryExpression = (UnaryExpression)lambda.Body;
memberExpression = (MemberExpression)unaryExpression.Operand;
}
else
{
memberExpression = (MemberExpression)lambda.Body;
}
return memberExpression.Member.Name;
}
#endregion
}
In the next step I modifed Silverlight csproj file and added "en" culture to supported types
<SupportedCultures>en</SupportedCultures>
Furthermore in application resources I created and instance of LocalizationProxy class
<Application.Resources>
<Localization:LocalizationProxy x:Key="LocalizationProxy"></Localization:LocalizationProxy>
</Application.Resources>
I also changed "Neutral Language" in Assembly Information to "Polish" - this should be default application language. In the last step I bouned some values from view to the resources
<TextBlock TextWrapping="Wrap" x:Name="PageTitle" Text="{Binding Source={StaticResource LocalizationProxy},Path=LocalizationManager.Title,Mode=TwoWay}" />
Unfortunatelly despite the fact that Thread.CurrentThread.CurrentCulture is "pl-PL" my application is still in English language.However if I use the same code in Windows Phone application everything works fine - I can even change application language in runtime. Is there any difference in localizing Silverlight application and localizing Windows Phone apps ?
Here is my application
http://www.fileserve.com/file/TkQkAhV/LocalizationSolution.rar
As I mentioned before, Localization in Windows Phone works fine, but in Silverlight application labels are not translated
You should use the fully qualified ISO 3166 and 639 codes combined with a hyphen as Rumplin describes.
see
http://en.wikipedia.org/wiki/List_of_ISO_639-1_codes
http://en.wikipedia.org/wiki/ISO_3166-1
make sure you made all the steps bellow properly.
Create your ViewModel Class
Implement the INotifyPropertyChanged interface:
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged(string propertyName)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
Create the property that will return the right language:
public object MainResourcesSmart
{
get
{
var myCulture = Thread.CurrentThread.CurrentUICulture.Name.ToUpper();
switch (myCulture)
{
case "EN-US":
return new MyResourceEn();
case "ES-AR":
return new MyResourceEs();
default:
return new MyResource();
}
}
}
Set all resources to public
Use the method bellow to refresh it on screen every time you change the language:
private void MainResourcesSmartRefresh()
{
OnPropertyChanged("MainResourcesSmart");
}
Bind the ViewModel to your View (MainPage) for example:
public MyViewModel ViewModel
{
get { return (MyViewModel)DataContext; }
set { DataContext = value; }
}
public MainPage()
{
ViewModel = new MyViewModel();
}
Bind the Resouce property to your UserControl like:
<TextBlock Height="20" HorizontalAlignment="Left" VerticalAlignment="Bottom" Foreground="#7F4F8AB2" FontSize="10.667" Text="{Binding MainResourcesSmart.NameOfTheCompany}" FontFamily="Trebuchet MS" />

Resources