Hi Xamarin GODS and GODDESSES. I am trying to find the solution to bind images selected with Media Picker (capture photo) and Media Gallery (pick photos), in order to save them on the local SQLite database and display them on the List View later on. I have two buttons event handlers for taking photos from a camera and picking photos from a gallery. They are both similar methods (Also, is there a better method for those two methods to avoid stream?). However, I am unsure how to bind their results and display them in my List View and SQLite database. There is a save button on the page that saves all inputs made by users such as Title, experience, location, and images (which I am struggling with, how to save images?). When the save button is clicked, changes are presented in List view and SQLite. It is quite easy to do that for text entry. However, how to do it for images???? I assume it should be somehow converted into bytes and arrays. But how? Please help!!!! Below is my code with mentioned methods and how I am displaying it to the List View. So basically, what I want to do is, have user's input in terms of EXPERIENCE, TITLE, LOCATION and IMAGE. Have it in my model Post class, save it to the SQ and display it in the list view.
XAML.CS
namespace GetAroundCroatia
{
[XamlCompilation(XamlCompilationOptions.Compile)]
public partial class IznajmiIznajmljivaciPage1 : ContentPage
{
public IznajmiIznajmljivaciPage1()
{
InitializeComponent();
}
private async void takePhoto_Clicked(object sender, EventArgs e)
{
var photo = await MediaPicker.CapturePhotoAsync();
if (photo != null)
{
var stream = await photo.OpenReadAsync();
resultImage.Source = ImageSource.FromStream(() => stream);
}
}
private async void pickPhotos_Clicked(object sender, EventArgs e)
{
var results = await MediaGallery.PickAsync(3, MediaFileType.Image);
if(results != null)
{
var imageList = new List<ImageSource>();
foreach (var media in results.Files)
{
var stream = await media.OpenReadAsync();
imageList.Add(ImageSource.FromStream(() => stream));
}
collectionView.ItemsSource = imageList;
}
}
private void save_Clicked(object sender, EventArgs e)
{
try
{
PostClass post = new PostClass()
{
Experience = experienceEntry.Text,
Title = titleEntry.Text,
Location = locationEntry.Text,
};
using (SQLiteConnection conn = new SQLiteConnection(App.DatabaseLocation))
{
conn.CreateTable<PostClass>();
int rows = conn.Insert(post);
if (rows > 0)
DisplayAlert("Uspjesno", "Oglas Predan", "OK");
else
DisplayAlert("Neuspjesno", "Oglas nije predan", "OK");
}
}
catch (NullReferenceException nre)
{
}
catch(Exception ex)
{
}
}
}
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="GetAroundCroatia.IznajmiIznajmljivaciPage1">
<ContentPage.ToolbarItems>
<ToolbarItem x:Name="Save" Text="Predaj" Clicked="save_Clicked"/>
</ContentPage.ToolbarItems>
<ContentPage.Content>
<ScrollView>
<StackLayout>
<Button x:Name="takePhoto" Text="Uslikaj" Clicked="takePhoto_Clicked"/>
<Image x:Name="resultImage"/>
<Button x:Name="pickPhotos" Text="Odaberi iz galerije" Clicked="pickPhotos_Clicked"/>
<CollectionView x:Name="collectionView">
<CollectionView.ItemTemplate>
<DataTemplate>
<Image Source="{Binding .}" />
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
<Label Text="Opci Podaci"/>
<Entry x:Name="titleEntry"
Placeholder="Title"/>
<Entry x:Name="experienceEntry"
Placeholder="Opis"/>
<Entry x:Name="locationEntry"
Placeholder="Unesi Lokaciju"/>
<Entry x:Name="raspolozivostEntry"
Placeholder="Odaberi Raspolozivost"/>
<Entry x:Name="dostavaEntry"
Placeholder="mogucnost dostave"/>
<Entry x:Name="soferopcijaEntry"
Placeholder="Mogucnost Vozac" />
</StackLayout>
</ScrollView>
</ContentPage.Content>
</ContentPage>
Model POST CLASS:
public class PostClass
{
[PrimaryKey, AutoIncrement]
public int Id { get; set; }
[MaxLength(300)]
public string Experience { get; set; }
public string Title { get; set; }
public string Location { get; set; }
}
List View XAML:
<ListView x:Name="PostListViewOglasi"
ItemTapped="PostListViewOglasi_ItemTapped">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<StackLayout Orientation="Horizontal" HorizontalOptions="CenterAndExpand" VerticalOptions="CenterAndExpand">
<Label Text="{Binding Title}" FontSize="15"/>
<Label Text="{Binding Experience}" FontSize="15"/>
<Label Text="{Binding Location}" FontSize="15"/>
</StackLayout>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
List View XAML.CS:
public OglasiListViewPage1()
{
InitializeComponent();
}
protected override void OnAppearing()
{
base.OnAppearing();
using (SQLiteConnection conn = new SQLiteConnection(App.DatabaseLocation))
{
conn.CreateTable<PostClass>();
var posts = conn.Table<PostClass>().ToList();
PostListViewOglasi.ItemsSource = posts;
}
}
private void PostListViewOglasi_ItemTapped(object sender, ItemTappedEventArgs e)
{
var selectedPost = PostListViewOglasi.SelectedItem as PostClass;
if(selectedPost != null)
{
Navigation.PushAsync(new DetaljiPostOglasaPage1(selectedPost));
}
}
}
CodePudding user response:
Media Picker (capture photo) and Media Gallery (pick photos)
What nuget do you used in your project?
And it is recommended that you use Xamarin.Essentials: Media Picker to achieve this.
You can get the FullPath
of your image except the stream
after you capture an image.
Please refer the following code:
async void CapturePhoto_Clicked(System.Object sender, System.EventArgs e)
{
var result = await MediaPicker.CapturePhotoAsync();
if (result != null)
{
var stream = await result.OpenReadAsync();
resultImage.Source = ImageSource.FromStream(() => stream);
string imagePath = result.FullPath;// get the fullpath and save to database
}
}
For saving your image to database , you can just add a new property ,for example:
public string imagePath { get; set; }`
to your class PostClass
and save the imagePath
to your database.
You can also use method MediaPicker.PickPhotoAsync
to pick photos.
Please refer to the following code:
async void Button_Clicked(System.Object sender, System.EventArgs e)
{
var result = await MediaPicker.PickPhotoAsync(new MediaPickerOptions
{
Title = "Please pick a photo"
});
if (result != null)
{
var stream = await result.OpenReadAsync();
resultImage.Source = ImageSource.FromStream(() => stream);
string path = result.FullPath;
}
}
Note:
How to bind picked images to the local SQLite database and display them on the page different from the page
For how to load images from database, you can refer to the following thread:Images saved in database are not displaying in the Home.xaml page in Xamarin Forms app .
CodePudding user response:
Thanks to @Jessie Zhang and @ Jason, I found the solution. Thus, I am sharing it with others who could potentially encounter a similar problem. I declared the imagePath string outside the capture photo method and accessed it in my Capture photo method and in my Save button method. Below is a complete code on how I captured the photo, saved it in the local SQLite, and displayed it in my list view. Thanks for the help, guys.
public partial class IznajmiIznajmljivaciPage1 : ContentPage
{
public IznajmiIznajmljivaciPage1()
{
InitializeComponent();
}
string imagePath;
private async void takePhoto_Clicked(object sender, EventArgs e)
{
var photo = await MediaPicker.CapturePhotoAsync();
if (photo != null)
{
var stream = await photo.OpenReadAsync();
resultImage.Source = ImageSource.FromStream(() => stream);
imagePath = photo.FullPath;
}
}
private void save_Clicked(object sender, EventArgs e)
{
try
{
PostClass post = new PostClass()
{
Experience = experienceEntry.Text,
Title = titleEntry.Text,
Location = locationEntry.Text,
imagePath = imagePath
};
using (SQLiteConnection conn = new SQLiteConnection(App.DatabaseLocation))
{
conn.CreateTable<PostClass>();
int rows = conn.Insert(post);
if (rows > 0)
DisplayAlert("Uspjesno", "Oglas Predan", "OK");
else
DisplayAlert("Neuspjesno", "Oglas nije predan", "OK");
}
}
catch (NullReferenceException nre)
{
}
catch(Exception ex)
{
}
POST CLASS:
public string imagePath { get; set; }
LIST VIEW:
<Image Source="{Binding imagePath}"/>