I hit a block and I want to save an Image into my Database alongside its Name, Description, and Price but when I display it, only the Name, Description, and Price are being displayed. I want to know if I used the correct method.
This is what my code looks like:
SQLiteHelper.cs:
using System.Collections.Generic;
using System.Text;
using SQLite;
using System.Threading.Tasks;
using projectDev.Model;
using System.IO;
namespace projectDev
{
public class SQLiteHelper
{
private readonly SQLiteAsyncConnection db;
public SQLiteHelper(string dbPath)
{
db = new SQLiteAsyncConnection(dbPath);
db.CreateTableAsync<ProductModel>();
}
public Task<int> CreateProduct(ProductModel product)
{
return db.InsertAsync(product);
}
public Task<List<ProductModel>> ReadProducts()
{
return db.Table<ProductModel>().ToListAsync();
}
public Task<int> UpdateProduct(ProductModel product)
{
return db.UpdateAsync(product);
}
public Task<int> DeleteProduct(ProductModel product)
{
return db.DeleteAsync(product);
}
public Task<List<ProductModel>> Search(string search)
{
return db.Table<ProductModel>().Where(p => p.Name.StartsWith(search)).ToListAsync();
}
}
}
This is where the user enters a new item:
<popup:PopupPage
xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:popup="clr-namespace:Rg.Plugins.Popup.Pages;assembly=Rg.Plugins.Popup"
x:Class="projectDev.ProductDetail">
<StackLayout
Margin="20"
HorizontalOptions="Center"
VerticalOptions="Center"
WidthRequest="350"
HeightRequest="660"
BackgroundColor="#61892f" >
<ImageButton x:Name="imageEntry" Source="addimage.png" Clicked="Button_Clicked_1"
MinimumHeightRequest="500"
BackgroundColor="Transparent"/>
<Entry Placeholder="Name"
x:Name="nameEntry" />
<Entry Placeholder="Description"
x:Name="descEntry"/>
<Entry Placeholder="Price"
x:Name="priceEntry"/>
<Button Text="Save"
Clicked="Button_Clicked"/>
</StackLayout>
</popup:PopupPage>
Code-Behind:
using System.IO;
using System.Threading.Tasks;
using Xamarin.Forms;
using Xamarin.Forms.Xaml;
using Plugin.Media;
using Plugin.Media.Abstractions;
using projectDev.Model;
namespace projectDev
{
[XamlCompilation(XamlCompilationOptions.Compile)]
public partial class ProductDetail : Rg.Plugins.Popup.Pages.PopupPage
{
byte[] imageData;
ProductModel _product;
public ProductDetail()
{
InitializeComponent();
}
public ProductDetail(ProductModel product) : this()
{
Title = "Edit Product";
_product = product;
nameEntry.Text = product.Name;
descEntry.Text = product.Description;
priceEntry.Text = product.Price;
imageEntry.Source = ImageSource.FromStream(() => new MemoryStream(product.Image));
nameEntry.Focus();
}
async void Button_Clicked(object sender, EventArgs e)
{
if (string.IsNullOrWhiteSpace(nameEntry.Text) || string.IsNullOrWhiteSpace(descEntry.Text) || string.IsNullOrWhiteSpace(priceEntry.Text))
{
await DisplayAlert("Invalid", "Blank is Invalid!", "OK");
return;
}
byte[] imageArray = imageData ?? (_product?.Image ?? Array.Empty<byte>());
if (_product != null)
{
_product.Name = nameEntry.Text;
_product.Description = descEntry.Text;
_product.Price = priceEntry.Text;
_product.Image = imageArray;
await App.MyDatabase.UpdateProduct(_product);
}
else
{
var newProduct = new ProductModel
{
Name = nameEntry.Text,
Description = descEntry.Text,
Price = priceEntry.Text,
Image = imageArray
};
await App.MyDatabase.CreateProduct(newProduct);
}
await Navigation.PopAsync();
}
async void Button_Clicked_1(object sender, EventArgs e)
{
await UploadPhoto();
}
async Task UploadPhoto()
{
await CrossMedia.Current.Initialize();
if (!CrossMedia.Current.IsPickPhotoSupported)
{
await DisplayAlert("Photos Not Supported", "Permission not granted to photos.", "OK");
return;
}
var file = await CrossMedia.Current.PickPhotoAsync(new PickMediaOptions
{
PhotoSize = PhotoSize.Full,
CompressionQuality = 40
});
if (file == null)
return;
imageData = File.ReadAllBytes(file.Path);
imageEntry.Source = ImageSource.FromStream(() => file.GetStream());
}
}
}
and this is where I want the Items to be displayed:
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:Plugin.Media;assembly=Plugin.Media"
x:Class="projectDev.ItemPage">
<ContentPage.Resources>
<local:CrossMedia x:Key="ImageByteArrayToImageSourceConverter" />
</ContentPage.Resources>
<ContentPage.ToolbarItems>
<ToolbarItem Text="Add"
IconImageSource="add.png"
Clicked="ToolbarItem_Clicked"/>
</ContentPage.ToolbarItems>
<StackLayout>
<StackLayout Margin="10">
<SearchBar TextChanged="SearchBar_TextChanged" Placeholder="Search Items..." PlaceholderColor="White" TextColor="White" BackgroundColor="#6b6e70"/>
</StackLayout>
<CollectionView x:Name="myCollectionView"
SelectionMode="Single"
Margin="20, 5, 20, 0">
<CollectionView.ItemTemplate>
<DataTemplate>
<SwipeView>
<SwipeView.RightItems>
<SwipeItems>
<SwipeItem Text="Edit"
BackgroundColor="Green"
CommandParameter="{Binding .}"
Invoked="SwipeItem_Invoked"/>
<SwipeItem Text="Delete"
BackgroundColor="Red"
CommandParameter="{Binding .}"
Invoked="SwipeItem_Invoked_1"/>
</SwipeItems>
</SwipeView.RightItems>
<Grid RowSpacing="0">
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="20"/>
</Grid.ColumnDefinitions>
<Image Source="{Binding Image}"
Grid.Row="0" Grid.RowSpan="3" Grid.Column="0"
HeightRequest="50" WidthRequest="50" Aspect="AspectFill"/>
<Label Text="{Binding Name}"
Grid.Row="0" Grid.Column="1"
VerticalOptions="CenterAndExpand"
FontSize="20"
FontAttributes="Bold"/>
<Label Text="{Binding Description}"
Grid.Row="1" Grid.Column="1"/>
<Label Text="{Binding Price}"
Grid.Row="2" Grid.Column="1"/>
</Grid>
</SwipeView>
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
</StackLayout>
</ContentPage>
Code-Behind:
using Rg.Plugins.Popup.Pages;
using Rg.Plugins.Popup.Services;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Xamarin.Forms;
using Xamarin.Forms.Xaml;
namespace projectDev
{
[XamlCompilation(XamlCompilationOptions.Compile)]
public partial class ItemPage : ContentPage
{
public ItemPage()
{
InitializeComponent();
}
protected override async void OnAppearing()
{
try
{
base.OnAppearing();
myCollectionView.ItemsSource = await App.MyDatabase.ReadProducts();
}
catch { }
}
async void ToolbarItem_Clicked(object sender, EventArgs e)
{
await PopupNavigation.Instance.PushAsync(new ProductDetail());
}
async void SwipeItem_Invoked(object sender, EventArgs e)
{
var item = sender as SwipeItem;
var emp = item.CommandParameter as ProductModel;
await PopupNavigation.Instance.PushAsync(new ProductDetail(emp));
}
async void SwipeItem_Invoked_1(object sender, EventArgs e)
{
var item = sender as SwipeItem;
var emp = item.CommandParameter as ProductModel;
var result = await DisplayAlert("Delete", $"Delete {emp.Name} from the Database?", "Yes", "No");
if (result)
{
await App.MyDatabase.DeleteProduct(emp);
myCollectionView.ItemsSource = await App.MyDatabase.ReadProducts();
}
}
private async void SearchBar_TextChanged(object sender, TextChangedEventArgs e)
{
myCollectionView.ItemsSource = await App.MyDatabase.Search(e.NewTextValue);
}
}
}
ProductModel:
using System.Collections.Generic;
using System.Text;
using SQLite;
using Xamarin.Forms;
using System.IO;
namespace projectDev.Model
{
public class ProductModel
{
[PrimaryKey, AutoIncrement]
public int Id { get; set; }
[MaxLength(50)]
public string Name { get; set; }
public string Description { get; set; }
public string Price { get; set; }
public byte[] Image { get; set; }
}
}