Xamarin - How to display en Image from an Object property - image

In xamarin I have a class where one of the property is an "IMAGE type".
I got this image from one Cloud API I developed myself.
I want now to display this image through a ListView and ImageCell. I'm wondering if there is is a way to bind my "Image" from my object directly thanks to the "ImageSource".
The class is declared the following(indeed the image is created from Byte[]:
public class Item
{
public int ItemId { get; set; }
public string Name { get; set; }
public decimal UnitPrice { get; set; }
public string Description { get; set; }
public string Brand { get; set; }
public bool HasSize { get; set; }
//public virtual List<SizedMeal> AvailableSizes { get; set; }
public bool CanBeSalt { get; set; }
public bool CanBeHotNotCold { get; set; }
public bool CanHaveMeat { get; set; }
public bool CanHaveSauce { get; set; }
public Image Image { get; set; }
}
Where IMAGE is comming from using Xamarin.Forms
and the object is constructed the following way:
Image image = new Image();
Stream stream = new MemoryStream(item.Image);
image.Source = ImageSource.FromStream(() => { return stream; });
ImageSource imageSource = image.Source;
resto.Menu.ItemList.Add(new Item
{
Name = item.Name,
Brand = item.Brand,
Image = image,
UnitPrice = item.UnitPrice,
Description = item.Description,
HasSize = item.HasSize,
ItemId = item.ItemId,
});
Thanks,

Related

How to add custom text to Picker's ItemDisplayBinding in Xamarin Forms

I want to add A custom text to my Picker. I have a picker the ItemsSource and ItemDisplayBinding binds from my database How can I add a custom text to my ItemDisplayBinding I want to mix Retailer Code with PresStreet and format to "Retailer Code - Street" My table is below for reference
Picker Title="Select Retailer Code" x:Name="codePicker" SelectedIndexChanged="codePicker_SelectedIndexChanged" ItemsSource="{Binding RetailerCode}" ItemDisplayBinding="{Binding RetailerCode}" StyleClass="fieldForm" IsEnabled="False"
My code below is how I get the data from my database and add the data to my picker
var db = DependencyService.Get<ISQLiteDB>();
var conn = db.GetConnection();
var getCode = conn.QueryAsync<RetailerGroupTable>("SELECT * FROM tblRetailerGroup WHERE ContactID=?", item.ContactID);
var resultCount = getCode.Result.Count;
if (resultCount > 0)
{
var result = getCode.Result;
codePicker.ItemsSource = result;
codePicker.IsEnabled = true;
}
else
{
lstName.IsVisible = false;
codePicker.IsEnabled = false;
}
My retailer group table:
[Table("tblRetailerGroup")]
public class RetailerGroupTable
{
[PrimaryKey, MaxLength(100)]
public string RetailerCode { get; set; }
public int ContactID { get; set; }
[MaxLength(300)]
public string PresStreet { get; set; }
[MaxLength(90)]
public string PresBarangay { get; set; }
[MaxLength(90)]
public string PresDistrict { get; set; }
[MaxLength(90)]
public string PresTown { get; set; }
[MaxLength(90)]
public string PresProvince { get; set; }
[MaxLength(90)]
public string PresCountry { get; set; }
[MaxLength(30)]
public string Telephone1 { get; set; }
[MaxLength(30)]
public string Telephone2 { get; set; }
[MaxLength(20)]
public string Mobile { get; set; }
[MaxLength(50)]
public string Email { get; set; }
[MaxLength(200)]
public string GPSCoordinates { get; set; }
[MaxLength(100)]
public string Coordinator { get; set; }
public DateTime LastSync { get; set; }
public DateTime ServerUpdate { get; set; }
public DateTime MobileUpdate { get; set; }
}
add a read only property to your class RetailerGroupTable
public string DisplayText {
get {
return $"{RetailerCode} - {PresStreet}";
}
}
and then bind to it
<Picker ItemDisplayBinding="{Binding DisplayText}" ... />

Generate barcode using Zxing in xamarin.forms

I am trying to display a barcode in my app using binding in my xaml. My question is how can I convert the barcode to be used in the xaml Image source. I have tried using a byte property but I get this compile error : "Cannot implicitly convert Zxing barcode image view to 'byte'". Any guidance on how to achieve this will be appreciate, thanks.
Cards.cs
public class Cards
{
public int CustomerID { get; set; }
public int DiscountLevelID { get; set; }
public string DiscountLevel { get; set; }
public double DiscountLevelAmount { get; set; }
public bool StoreCustomerGiftCard { get; set; }
public bool StoreCustomerLoyalty { get; set; }
public int LoyaltyLevelID { get; set; }
public string LoyaltyLevel { get; set; }
public double LoyaltyLevelRatio { get; set; }
public double Balance { get; set; }
public int StoreNumber { get; set; }
public string CardNumber { get; set; }
public bool IsError { get; set; }
public object ErrorMessage { get; set; }
public string CompanyName { get; set; }
public string CustomerLogo { get; set; }
public byte BarCode { get; set; }
}
Cards.xaml.cs
ZXingBarcodeImageView barcode;
barcode = new ZXingBarcodeImageView { HorizontalOptions = LayoutOptions.FillAndExpand, VerticalOptions = LayoutOptions.FillAndExpand };
barcode.BarcodeFormat = ZXing.BarcodeFormat.QR_CODE;
barcode.BarcodeOptions.Width = 300;
barcode.BarcodeOptions.Height = 300;
barcode.BarcodeOptions.Margin = 10;
barcode.BarcodeValue = i.CardNumber;
i.BarCode = barcode;
Cards.xaml
<Image Source="{Binding BarCode}" />
ZXingBarcodeImageView inherits directly from Image, so you use it as an alternative to Image, not as a source for Image
xmlns:zx="clr-namespace:ZXing.Net.Mobile.Forms;assembly=ZXing.Net.Mobile.Forms"
xmlns:zxcm="clr-namespace:ZXing.Common;assembly=zxing.portable"
<zx:ZXingBarcodeImageView
BarcodeFormat="QR_CODE"
BarcodeValue="{Binding CardNumber}"
HorizontalOptions="FillAndExpand"
VerticalOptions="FillAndExpand">
<zx:ZXingBarcodeImageView.BarcodeOptions>
<zxcm:EncodingOptions Width="300" Height="300" />
</zx:ZXingBarcodeImageView.BarcodeOptions>
</zx:ZXingBarcodeImageView>

Xamarin ImageSource in ListView not updating

I have a ListView that contains images, the images are fetched from a server. The first API call I make gets the data in var people. I load the listview with a placeholder image, then run the 2nd API call to get the images for each item in the listview. I receive a byte[] as the image, and I convert it to an ImageSource. I have a search button at the top of the page that I set binding to TempImage which uses the byte[] as its source, and it changes to the images that are loaded. So the conversion of byte[] to ImageSource is fine. The initial setting of p.PictureImageSource = "name_circle.png" also works correctly. However, setting p.PictureImageSource to the converted byte[] does NOT work. It never changes from the initial "name_circle.png". Any ideas?
var people = peopleModel.Response;
if(people.Count == 0)
{
ShowNoResults = true;
}
else
{
ShowNoResults = false;
Results = peopleModel.Response;
foreach (PersonViewModel p in Results)
{
p.Initials = p.FirstName[0].ToString() + p.LastName[0];
p.PictureImageSource = "name_circle.png";
}
}
//must do 2 seperate loops so the initials load before going on with 2nd search
foreach (PersonViewModel p in Results)
{
IsBusy = false;
var peopleImage = await peopleService.GetPersonImage("p.Email");
if ((peopleImage.Error == null) && (peopleImage.Response != null))
{
p.Picture = peopleImage.Response;
byte[] imageAsBytes = (byte[])peopleImage.Response;
p.PictureImageSource = ImageSource.FromStream(() => new MemoryStream(imageAsBytes));
TempImage = ImageSource.FromStream(() => new MemoryStream(imageAsBytes));
}
}
OnPropertyChanged();
-
public class PersonViewModel : INotifyPropertyChanged
{
public WorkstationViewModel WorkstationDetail { get; set; }
public List<PointViewModel> Points { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string FullName { get; set; }
public string Initials { get; set; }
public string Email { get; set; }
public string ID { get; set; }
public string Department { get; set; }
public string BuildingName { get; set; }
public string SiteID { get; set; }
public string BuildingID { get; set; }
public string FloorNumber { get; set; }
public string FloorID { get; set; }
public string Workstation { get; set; }
public string Title { get; set; }
public string Phone { get; set; }
public byte[] Picture { get; set; }
public ImageSource PictureImageSource { get; set; }
public event PropertyChangedEventHandler PropertyChanged;
}
Apineda was correct in thinking the listview wasn't refreshing at all with the new data. I separated the two API calls into two different methods (not sure if this part is entirely necessary). After the completion of the 2nd call, I set the listview's ItemSource to null, then back to the Results value, forcing a refreshing. Now the images show.
searchGestureRecognizer.Tapped += async (s, e) => {
await _viewModel.GetResults();
await _viewModel.GetImagesForResults();
resultsListView.ItemsSource = null;
resultsListView.ItemsSource = _viewModel.Results;
};

Where should i place methods that map my ViewModel?

I have the following ViewModel, which is the base class of other ViewModels that inherit it.
Is it a good idea, to place the method that maps the viewmdoel in the viewmodel it self?
Like this:
public class ShowQuestionViewModel
{
public ShowQuestionViewModel()
{
}
public int Question_ID { get; set; }
public Boolean Condition_Fullfilled;
public String requiredmessage = "";
[Required(ErrorMessage = "Dette felt er påkrævet")]
public String Question_Wording { get; set; }
public String Question_Type { get; set; }
[Required(ErrorMessage = "Dette felt er påkrævet")]
//[Digits(ErrorMessage = "Feltet må kun indeholde heltal")]
public String Question_Number { get; set; }
public String Left_scale { get; set; }
public String Right_scale { get; set; }
public int Scale_Length { get; set; }
public String Left_Scale_HelpText { get; set; }
public String Right_Scale_HelpText { get; set; }
public Boolean Visible { get; set; }
public Boolean IsAnswered { get; set; }
public String Question_HelpText { get; set; }
public String Question_HelpText_PDF { get; set; }
public int Category_ID { get; set; }
// Ting der er behov for til Views
public SelectList Categories { get; set; }
public SelectList Visibility { get; set; }
public string RefUrl { get; set; }
public void MapQuestionToViewModel(MvcApplication3.Models.Question question)
{
Question_ID = question.question_id;
Category_ID = Convert.ToInt32(question.category_id);
Question_Number = question.question_number.ToString();
Question_Wording = question.question_wording;
Visible = (bool)question.visible;
String hlptxt = question.help_text;
Question_HelpText = hlptxt;
Question_HelpText_PDF = question.help_text_pdf ?? "";
Left_scale = question.left_scale;
Right_scale = question.right_scale;
Scale_Length = question.scale_length ?? 0;
Left_Scale_HelpText = question.left_scale_hlptxt;
Right_Scale_HelpText = question.right_scale_hlptxt;
Question_Type = question.Question_Type.type_description;
Categories = GetQuestions.GetCategories(question);
Visibility = GetQuestions.getVisibleSelectList();
}
}
Or should it be placed somewhere else?
Links to some design-guidelines are welcome
I would use a second constructor instead
public ShowQuestionViewModel(MvcApplication3.Models.Question dbmodel)
The MvcApplication3.Models namespace should contain the view models and nothing else. I recommend that you move all business logic into a class library instead.
You don't have to take care of the mapping either. You could use a framework like AutoMapper or ValueInjecter.

How do upload and associate an image with another class simultaneously in MVC3

I have a class, Event, and i want to be able to have images on the event page. I have defined the image class but am now sure how i can upload the image. I want to be able to store the image in the database.
public class Event
{
public int Id { get; set; }
public string Title { get; set; }
public string Description { get; set; }
public string Address { get; set; }
public string AddressTwo { get; set; }
public virtual Person Owner { get; set; }
public DateTime Date { get; set; }
public virtual Image Image { get; set; }
}
public class Image
{
public int Id { get; set; }
public string Name { get; set; }
public string AlternateText { get; set; }
public virtual string CssClass { get; set; }
public Byte[] File { get; set; }
}
If you want to handle file uploads you should use the HttpPostedFileBase type to represent the image and not a byte array:
public class Image
{
public int Id { get; set; }
public string Name { get; set; }
public string AlternateText { get; set; }
public virtual string CssClass { get; set; }
public HttpPostedFileBase File { get; set; }
}
then in your view you will use a file input:
#model Event
#using (Html.BeginForm(null, null, FormMethod.Post, new { enctype = "multipart/form-data" }))
{
<div>
#Html.LabelFor(x => x.Image.File)
#Html.TextBox(x => x.Image.File, new { type = "file" })
</div>
... some other fields
<button type="submit">OK</button>
}
and finally you will have the controller action to which the form will be posted and which will save the file:
[HttpPost]
public ActionResult Upload(Event model)
{
if (model.Image != null && model.Image.ContentLength > 0)
{
// an image was selected by the user => process and store it into the database
}
...
}
You might also find the following blog post useful.

Resources