I am currently working on a image preview list for pictures that have been made on the mobile device itself. Later on those images will be stored in the database. However for the first iteration I was testing the list with images from web. I am using xamarin forms and the target is android. That is a picture of the page on the device I can not pinpoint the issue. I do not get any runtime exception. Maybe there is an issue with the binding.
[Updated the source code and cleaned it up]
Here is the view:
<?xml version="1.0" encoding="utf-8" ?>
<ui:BasePage
x:Class="AssetManagement.Mobile.Core.UI.OrderItemImageDocumentationPage"
xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:actionMenu="clr-namespace:Client.ApplicationDataModel.UI.Controls.ActionMenu;assembly=Client.ApplicationDataModel.UI"
xmlns:controls="clr-namespace:AssetManagement.Mobile.Core.Controls"
xmlns:controls1="clr-namespace:UI.XF.Controls;assembly=UI"
xmlns:res="clr-namespace:AssetManagement.Mobile.Core.Resources"
xmlns:ui="clr-namespace:AssetManagement.Mobile.Core.UI"
xmlns:valueconverter="clr-namespace:AssetManagement.Mobile.Core.Classes.ValueConverter"
xmlns:viewmodel="clr-namespace:AssetManagement.Mobile.Core.ViewModels"
Title="Bild Dokumentation"
x:TypeArguments="viewmodel:OrderItemImageDocuViewModel"><!--{res:Translate OrderItemImageDocumentary}-->
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<StackLayout Grid.Row="0" Grid.Column="0" Grid.ColumnSpan="3">
<ListView ItemsSource="{Binding OrderItemImages}"
HasUnevenRows="true"
ItemSelected="OnListViewItemSelected"
ItemTapped="OnListViewItemTapped">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<Grid Padding="10">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Image Grid.RowSpan="2"
Source="{Binding ImageData}"
Aspect="AspectFit"
HeightRequest="200"
WidthRequest="200" />
<Label Grid.Column="1"
Text="{Binding Title}"
FontAttributes="Bold" />
<Label Grid.Row="1"
Grid.Column="1"
Text="test"
VerticalOptions="End" />
</Grid>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</StackLayout>
<StackLayout Grid.Row="1" Grid.ColumnSpan="3" Grid.Column="0" Orientation="Horizontal">
<Button x:Name="BtnCancel"
AutomationId="BtnCancel"
Text="Cancel"
Clicked="BtnCancel_OnClicked"
Style="{StaticResource DefaultButtonStyle}" />
<Button x:Name="BtnSave"
AutomationId="BtnSave"
Text="Save"
Clicked="BtnSave_OnClicked"
Style="{StaticResource DefaultButtonStyle}" />
</StackLayout>
</Grid>
</ui:BasePage>
The associated code behind:
[XamlCompilation(XamlCompilationOptions.Compile)]
public partial class OrderItemImageDocumentationPage : BasePage<OrderItemImageDocuViewModel>
{
private IAppConfiguration _appConfig;
public OrderItemImageDocumentationPage()
{
InitializeComponent();
}
public OrderItemImageDocumentationPage(OrderItemImageDocuViewModel viewModel, IEventLogService eventLog, ILifetimeScope scope,
IUserInterfaceService uiService, IAppConfiguration appConfig)
: base(viewModel, eventLog, scope, uiService)
{
InitializeComponent();
_appConfig = appConfig;
}
private void BtnSave_OnClicked(object sender, EventArgs e)
{
var test = new OrderItemImageDocData(Title = "test", Xamarin.Forms.ImageSource.FromUri(new Uri(@"https://upload.wikimedia.org/wikipedia/commons/7/7b/Dark_brown.PNG")));
base.ViewModel.OrderItemImages.Add(test);
base.ViewModel.OrderItemImages.Last().ImageData = Xamarin.Forms.ImageSource.FromUri(new Uri(@"https://upload.wikimedia.org/wikipedia/commons/7/7b/Dark_brown.PNG"));
}
}
My current View Model:
public class OrderItemImageDocuViewModel : ApplicationDataBaseViewModel, INavigationEventHandler
{
#region Klassenvariablen
private readonly int _pagingSize = 20;
private IAppConfiguration _appConfig;
private ILifetimeScope _scope;
private IBarcodeParserService _barcodeParser;
private IEventLogService _eventLog;
private IUserDataService _userData;
private int _itemsToLoadCount;
private ObservableCollection<OrderItemImageDocData> _orderItemImages = new ObservableCollection<OrderItemImageDocData>();
private OrderItem _orderItemContext = null;
#endregion Klassenvariablen
#region Konstruktor
public OrderItemImageDocuViewModel(ILifetimeScope scope, IDataRepositoryService dataRepository, IBarcodeParserService barcodeParserService, IEventLogService eventLog, IUserDataService userData, ITranslationService translationService, IAppConfiguration appConfig)
: base(dataRepository)
{
_eventLog = eventLog.Initialize(typeof(OrderItemImageDocuViewModel));
_scope = scope;
_appConfig = appConfig;
_userData = userData;
_barcodeParser = barcodeParserService;
TranslationService = translationService;
_itemsToLoadCount = _pagingSize;
//DatabasesMissing = !dataRepository.IsDataStoreFileAvailable(DownloadDataFileType.TransactionData);
//if (!DatabasesMissing)
//{
// IsLoading = true;
//}
}
#endregion Konstruktor
#region Properties
[NavigationParameter]
public Order Order { get; set; }
public IEventLogService EventLog => _eventLog;
public bool IsLoading { get; set; }
public bool DatabasesMissing { get; set; }
public ITranslationService TranslationService { get; set; }
public IList<OrderItem> OrderItems { get; set; }
public IOrderTypeScanHandling ScanHandler { get; set; }
public ObservableCollection<OrderItemImageDocData> OrderItemImages
{
get
{
return _orderItemImages;
}
set
{
_orderItemImages = value;
base.OnPropertyChanged("OrderItemImages");
}
}
#endregion Properties
public override async void OnNavigationParametersProvided(NavigationContext context)
{
if (!DatabasesMissing)
{
IsLoading = true;
try
{
//await InitializeData();
//await LoadDataOnDemand();
}
catch (Exception ex)
{
//ex.TrackError();
}
IsLoading = false;
}
}
}
This is the class currently holding the Image data. This is just a quick and dirty placeholder. Since the vs designer is rather poor and not working I needed some class that just provides image data so i can design the ui page the way i want it.
public class OrderItemImageDocData : INotifyPropertyChanged
{
#region Events
public event PropertyChangedEventHandler PropertyChanged;
#endregion
#region Fields
private string _title = string.Empty;
private ImageSource _imageData;
#endregion
#region Constr
public OrderItemImageDocData()
{
}
public OrderItemImageDocData(string title, ImageSource imgData)
{
_title = title;
ImageData = imgData;
}
#endregion
#region Properties
public string Title
{
get
{
return _title;
}
set
{
_title = value;
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs("Title"));
}
}
public ImageSource ImageData
{
get
{
return _imageData;
}
set
{
_imageData = value;
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs("ImageData"));
}
}
#endregion
}
The permissions I have in my android manifest file.
<uses-permission android:name="android.permission.FLASHLIGHT" />
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.VIBRATE" />
[Update] I am not sure why I did not notice it earlier. Probably because while being in debug he did not throw an exception. However there must be a runtime exception. The vs output windows shows this whenever I try to add a new list view item (and thatfor a new image):
05-28 08:09:43.563 D/skia ( 7653): --- SkImageDecoder::Factory returned null
05-28 08:09:43.619 W/art ( 7653): JNI RegisterNativeMethods: attempt to register 0 native methods for md51558244f76c53b6aeda52c8a337f2c37.CellRenderer_RendererHolder
[0:] ImageLoaderSourceHandler: Could not retrieve image or image data was invalid: Uri: https://upload.wikimedia.org/wikipedia/commons/7/7b/Dark_brown.PNG
05-28 08:09:43.703 I/Choreographer( 7653): Skipped 38 frames! The application may be doing too much work on its main thread.
Thread finished: <Thread Pool> #2
The information however is rather poor. Tried multiple different images with the same output result.
Latest Update: Sadly I can not post a solution for this problem in case others have similar issues please try the answers from Mihail Duchev. He got some good pointers. However I switch from uri to stream source since i load the images from the database. Apparently that runtime exception only occurs for me while using uri ImageSource.