Share via


Need to retrieve Images (Var-binary MAX) from MSsqlserver 2014 by using C#

Question

Friday, August 11, 2017 3:46 AM

I am new to xamarin platform ,I have the local hosted database in MSsqlserver 2014 using php (with aid of XAMP server) and the table name ItemProductsDB and saved images as var-binary(MAX) . i m getting all the other details from database as a string (Example String Product Name, int Product ID, etc...) but the images as byte [] the class as below. namespace TestProject.Data { public class Contactone { public int ID { get; set; } public string Name { get; set; } public string Description { get; set; } public string Price { get; set; } public string Date { get; set; }
public byte[] Image { get; set; }
}

public class ContectList
{
    public List<Contactone> contacts { get; set; }
}

}

and i have already created the cs page and xaml to retrieve the other data except image, the code below JsonParsingPage.cs ( this below code runs just fine but no retrieving of images )...........................................

namespace TestProject.Views.DetailViews {

public partial class JsonParsingPage : ContentPage
{
    public JsonParsingPage()
    {
        InitializeComponent();
        this.BackgroundImage = "background.png";
        this.Title = "Meals";
        GetJSON();
    }
    public async void GetJSON()
    {

        //Check network status 
        if (NetworkCheck.IsInternet())
        {
            var client = new System.Net.Http.HttpClient();
            var response = await client.GetAsync("http://192.168.43.226/GetProducts.php");
            string contactsJson = response.Content.ReadAsStringAsync().Result;
            ContectList ObjContactList = new ContectList();
            if (contactsJson != "")
            {
                //Converting JSON Array Objects into generic list
                ObjContactList = JsonConvert.DeserializeObject<ContectList>(contactsJson);
            }
            //Binding listview with server response  
            listviewConacts.ItemsSource = ObjContactList.contacts;
        }
        else
        {
            await DisplayAlert("JSONParsing", "No network is available.", "Ok");
        }
        //Hide loader after server response  
       ProgressLoader.IsVisible = false;
    }       

}

The fronted Xaml code as below with binding respective fields .......................................................

x:Class="TestProject.Views.DetailViews.JsonParsingPage">

                </DataTemplate>
            </ListView.ItemTemplate>
        </ListView>
    </Grid>
    <ActivityIndicator x:Name="ProgressLoader" IsRunning="True"/>
</Grid>

so my question is that what do i have to do to reterve varbinary images from the sqlserver to xamarin froms ( including cs and XAML code) , Any help would be appreciated.

Pan

All replies (7)

Friday, August 11, 2017 2:02 PM âś…Answered

@PandukaWeerasekara , Try to use Converter Binding imagesource inside the listview

Create a ByteArrayToImageConverter class inside your application folder

public class ByteArrayToImageConverter : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {
            if (value == null)
                return null;
            var ByteArray = value as byte[];
            Stream stream = new MemoryStream(ByteArray);
            ImageSource ImageSrc = ImageSource.FromStream(() => stream);
            return ImageSrc;
        }

        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
        {
            return null;
        }
    }

Inside your Xaml page try to use <ContentPage.Resources>

             <ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
                         xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
                         x:Class="AppName.Views.Home" BackgroundColor="#343434"
                         xmlns:local="clr-namespace:AppName.Converter">
                <ContentPage.Resources>
                    <ResourceDictionary>
                        <local:SeverityTypeImageConverter x:Key="severityTypeImageConverter"/>
                    </ResourceDictionary>
                </ContentPage.Resources>......

Finally try to use like this..... <Image Source="{Binding SeverityType,Converter={StaticResource severityTypeImageConverter}}" />

Hope it helps.......


Saturday, August 12, 2017 6:12 AM

Thank you DeepakDeeps for the replay really appreciate it. but there is a little problem when i debug the program it dosen't through any errors but i cant open the page it get stuck ( dosen't open the intended page) . i went through the codeing as well i think the problem with xmlns:local="clr-namespace:AppName.Converter" because below i ll mention the converter class that i ave written

using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Xamarin.Forms;

namespace TestProject.Data
{
    public class ByteArrayToImageConverter : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {
            if (value == null)
                return null;
            var ByteArray = value as byte[];
            Stream stream = new MemoryStream(ByteArray);
            ImageSource ImageSrc = ImageSource.FromStream(() => stream);
            return ImageSrc;
        }
        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
        {
            return null;
        }
    }
}

And hear is the page i have created the xamal ..............................................................................................

        ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
                     xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"            
                     x:Class="TestProject.Views.DetailViews.JsonParsingPage"
                     xmlns:local ="clr-namespace:TestProject.Data">
            <ContentPage.Resources>
                <ResourceDictionary>
                    <local:SeverityTypeImageConverter x:Key="severityTypeImageConverter"/>
                </ResourceDictionary>
            </ContentPage.Resources>
            <Grid>
                <Grid>
                    <Grid.RowDefinitions>
                        <RowDefinition Height="Auto"/>
                        <RowDefinition Height="*"/>
                    </Grid.RowDefinitions>            
                    <ListView x:Name="listviewConacts" Grid.Row="1" HorizontalOptions="FillAndExpand" HasUnevenRows="True" ItemSelected="listviewContacts_ItemSelected">
                        <ListView.ItemTemplate>
                            <DataTemplate>
                                <ViewCell>
                                    <Grid HorizontalOptions="FillAndExpand" Padding="10">
                                        <Grid.RowDefinitions>
                                            <RowDefinition Height="Auto"/>
                                            <RowDefinition Height="Auto"/>
                                            <RowDefinition Height="Auto"/>
                                            <RowDefinition Height="Auto"/>
                                            <RowDefinition Height="Auto"/>
                                        </Grid.RowDefinitions>
                                        <Label Text="{Binding Name}" HorizontalOptions="StartAndExpand" Grid.Row="0" TextColor="White"  FontAttributes="Bold"/>
                                        <Label Text="{Binding Description}" HorizontalOptions="StartAndExpand" Grid.Row="1" TextColor="Orange"  FontAttributes="Bold"/>
                                        <Label Text="{Binding Price}" HorizontalOptions="StartAndExpand" Grid.Row="2" TextColor="Gray"  FontAttributes="Bold"/>
                                        <Label Text="{Binding Date}" HorizontalOptions="StartAndExpand" Grid.Row="3" TextColor="Gray"  FontAttributes="Bold"/>
                                        <Image Source="{Binding SeverityType,Converter={StaticResource severityTypeImageConverter}}" Grid.Row="4"/>
                                        <BoxView HeightRequest="2" Margin="0,10,10,0" BackgroundColor="Gray" Grid.Row="4" HorizontalOptions="FillAndExpand" />
                                    </Grid>
                                </ViewCell>
                            </DataTemplate>
                        </ListView.ItemTemplate>
                    </ListView>
                </Grid>
                <ActivityIndicator x:Name="ProgressLoader" IsRunning="True"/>
            </Grid>
        </ContentPage>

Can you kindly tell me what could be the possible reason to not through errors but cant open the page? Thank you in-advance for your support.


Tuesday, December 12, 2017 5:32 AM

@DeepakDeeps Thank you so much for the last few replies and so far the code works perfectly, but i m having memory issues, did you come across any similar issues ? Thanks .


Thursday, December 21, 2017 8:29 AM

Need more detail @PandukaWeerasekara


Thursday, December 21, 2017 8:49 AM

@DeepakDeeps i will send you the Relevant details , because now when we retrieve byte images from the SQL severer ( as a byte array decoded through PHP) because the list view create images using static recourse and consumes memory large scale, sometimes when see the list view after scrolling some times the device get stuck by saying out of memory ( due to running out of space ) , i have analyzed through xamarin profiler and i have the screen shots for you to see,

i will explain one by one 1. i used your above converter and its working smootly but increaing the memory everytime loads the list of images to the list view ( because its not cashing existing images)

namespace TestProject.Data
{
    public class ByteArrayToImageConverter : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {
            if (value == null)
                return null;
            var ByteArray = value as byte[];
            Stream stream = new MemoryStream(ByteArray);
            ImageSource ImageSrc = ImageSource.FromStream(() => stream);
            return ImageSrc;
        }
        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
        {
            return null;
        }
    }
}

so i change the converter as below but its gives the same results which is increasing memeory when images loads without cashing

namespace TestProject.Data
{
    public class ByteArrayToImageConverter : IValueConverter
    {
        // public ImageSource retSource;
        //MemoryStream ms;
        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {
            ImageSource imgsrc = null;
            try
            {
                if (value == null)
                    return null;
                byte[] bArray = (byte[])value;

                imgsrc = ImageSource.FromStream(() =>
                {
                    var ms = new MemoryStream(bArray);
                    // ms.Position = 0;
                    //imgsrc.CopyTo(ms);
                    //ms.Read(bArray, 0, (int)ms.Length); 
                    ms.FlushAsync();
                    ms.Flush();
                    if (value == imgsrc)
                    {
                        //var ms = new MemoryStream(bArray);
                        ms.Dispose();
                        ms.FlushAsync();
                        ms.Flush();
                    }
                    // ms.Dispose();  
                    ms.FlushAsync();
                    ms.Flush();
                    return ms;      

                });

                if (value == imgsrc)
                {
                    var ms = new MemoryStream(bArray);
                    ms.Dispose();
                }



            }
            catch (System.Exception sysExc)
            {
                System.Diagnostics.Debug.WriteLine(sysExc.Message);
            }
            return imgsrc;
        }

        public object ConvertBack(object value, Type targetType, object parameter,
          System.Globalization.CultureInfo culture)
        {
            throw new NotImplementedException();
        }
    }

I will include the screen shots what happens when we use the list view ( for your information i used the listview CachingStrategy="RecycleElement" but it dosen't work at all


Thursday, December 21, 2017 9:01 AM

Hear are the screen shots of the memeory usage (memeory leaking images )

and hear is the code for the listview XAml and the code behind

XAML Content page

<?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="TestProject.Views.DetailViews.FoodTabPage"
             xmlns:ff="clr-namespace:FFImageLoading.Forms;assembly=FFImageLoading.Forms" 
             xmlns:ctrls="clr-namespace:TestProject.Data;assembly=TestProject"
              xmlns:xamvvm="clr-namespace:Xamvvm;assembly=Xamvvm.Forms" 
             xmlns:local ="clr-namespace:TestProject.Data;assembly=TestProject">

    <ContentPage.Resources>
        <ResourceDictionary>
            <local:ByteArrayToImageConverter x:Key="severityTypeImageConvertertwo"/>
        </ResourceDictionary>
    </ContentPage.Resources>
    <ContentPage.ToolbarItems>
        <ToolbarItem Text="Search" Clicked="Search"/>
    </ContentPage.ToolbarItems>   
    <ContentPage.Content>       
            <StackLayout>
                <StackLayout x:Name="stackLayoutShowHide" IsVisible="False">
                    <Entry Placeholder="Your text to search" TextChanged="searchChanged" TextColor="Gray" BackgroundColor="White"/>
                </StackLayout>
            <ListView x:Name="mealsListView" HasUnevenRows="True" ItemSelected="listviewContacts_ItemSelected" CachingStrategy="RecycleElement" >                
                <ListView.ItemTemplate>
                    <DataTemplate>
                        <ViewCell>
                            <StackLayout  Orientation="Vertical" Padding="5">
                                <StackLayout Orientation="Horizontal"  BackgroundColor="Ivory" Opacity="0.9">
                                    <Image Source="{Binding Image,Converter={StaticResource severityTypeImageConvertertwo}}" HeightRequest="100" WidthRequest="100"/>
                                    <StackLayout Orientation="Vertical">
                                        <Label Text="{Binding Name}" FontSize="Medium" TextColor="Gray" FontAttributes="Bold"/>
                                        <BoxView HeightRequest="2" Margin="0,10,10,0" BackgroundColor="Gray" HorizontalOptions="FillAndExpand" />
                                        <Label Text="{Binding Description}" FontSize="Micro" TextColor="Gray" FontAttributes="Bold"/>
                                        <StackLayout Orientation="Horizontal" VerticalOptions="Start" HorizontalOptions="Start">
                                            <Label Text="$" FontSize="Micro" VerticalOptions="Start" HorizontalOptions="Start" TextColor="Gray" FontAttributes="Bold"/>
                                            <Label Text="{Binding Price}" FontSize="Micro" TextColor="Gray" FontAttributes="Bold"/>
                                        </StackLayout>
                                    </StackLayout>
                                    <Image Source="arrowtwo.png" BackgroundColor="Transparent" WidthRequest="25" Margin="0,10,10,0"/>
                                </StackLayout>
                            </StackLayout>
                        </ViewCell>
                    </DataTemplate>
                </ListView.ItemTemplate>
            </ListView>
        </StackLayout>
    </ContentPage.Content>    
    <!-- <ctrls:LSImage/>-->
</ContentPage>

code behind Content page

using System; using System.Collections; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Diagnostics; using System.Linq; using System.Text; using System.Threading.Tasks; using FFImageLoading; using Java.Util; using TestProject.Data; using Xamarin.Forms; using Xamarin.Forms.Xaml;

namespace TestProject.Views.DetailViews { [XamlCompilation(XamlCompilationOptions.Compile)] public partial class FoodTabPage : ContentPage {

    private IList<ResturentItems> _foodList;

    public FoodTabPage(string categoryName, IList<ResturentItems>foodList)
    {
        InitializeComponent();           
        this.BackgroundImage = "background.png";

        Title = categoryName;            
        mealsListView.ItemsSource = foodList;            

        _foodList = foodList;
    }

    public enum ListViewCachingStrategy
    {

        RetainElement,   // the default value
        RecycleElement,
        RecycleElementAndDataTemplate
    }


    private void Search(object sender, EventArgs e)
    {
        stackLayoutShowHide.IsVisible = !stackLayoutShowHide.IsVisible;
    }

    private void searchChanged(object sender, TextChangedEventArgs e)
    {
        if (string.IsNullOrWhiteSpace(e.NewTextValue))
            mealsListView.ItemsSource = _foodList;
        else
            mealsListView.ItemsSource = _foodList.Where(i => i.Name.ToLower().Contains(e.NewTextValue.ToLower()));
    }


    private void listviewContacts_ItemSelected(object sender, SelectedItemChangedEventArgs e)
    {
        var itemSelectedData = e.SelectedItem as ResturentItems;
        Navigation.PushAsync(new JsonDetailsPage(itemSelectedData.ID, itemSelectedData.Image, itemSelectedData.Name, itemSelectedData.Code, itemSelectedData.Description, itemSelectedData.Price, itemSelectedData.isservicecharge, itemSelectedData.CostPrice));

        GC.Collect();                  


    }       

    protected override void OnParentSet()
    {
        base.OnParentSet();

        if (Parent == null)
        {               
            BindingContext = mealsListView.ItemsSource = null;

        }

    }       
}

}

XAML of TAB page

<TabbedPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="TestProject.Views.DetailViews.FoodTabbedPage"            
             Title="FOOD MENU" >    
  <!--Pages can be added as references or inline
    <local:JsonDesertNew>
    </local:JsonDesertNew>-->

</TabbedPage>

Xcodebehind of TAB page

using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Text; using System.Threading.Tasks; using Newtonsoft.Json; using TestProject.Data; using Xamarin.Forms; using Xamarin.Forms.Xaml;

namespace TestProject.Views.DetailViews { [XamlCompilation(XamlCompilationOptions.Compile)] public partial class FoodTabbedPage : TabbedPage {
List ResturentList;

    public FoodTabbedPage()
    {         

        InitializeComponent();         
        this.BackgroundColor = Color.Maroon;
        Children.Add(new TabLoader());            

        ActivityIndicator ai = new ActivityIndicator
        {
            Color = Color.Black,
            IsRunning = true,
        };


        this.IsBusy = true;
        GetJSON();

        ToolbarItem serch = new ToolbarItem();
        serch.Order = ToolbarItemOrder.Secondary;
        serch.Text = "SERCH MORE";
        serch.Command = new Command(() => Navigation.PushAsync(new SearchItemsPage()));
        ToolbarItems.Add(serch);            
    }




    public async void GetJSON()
    {            
            var client = new System.Net.Http.HttpClient();               
            var response = await client.GetAsync("http://192.168.43.51/TabPageAll.php");
            string contactsJson = response.Content.ReadAsStringAsync().Result;
            if (response.IsSuccessStatusCode)
            {
                var list = JsonConvert.DeserializeObject<ResturentList>(contactsJson);

                ResturentList = new List<ResturentItems>(list.Resturent);
                IList<string> allCategories = ResturentList.Select(x => x.Category).ToList();
                allCategories = allCategories.Distinct().ToList();
                foreach (var category in allCategories)
                {

                Children.Add(new FoodTabPage(category, ResturentList.Where(x => x.Category == category).ToList()));                 

                }
            Children.Remove(Children.First());          

            }
            else
            {
                var textReader = new JsonTextReader(new StringReader(contactsJson));
                dynamic responseJson = new JsonSerializer().Deserialize(textReader);
                contactsJson = "Deserialized JSON error message: " + responseJson.Message;
                await DisplayAlert("fail", "no Network Is Available.", "Ok");
            }         

    }       

}

}


Monday, June 24, 2019 5:57 PM

hi @PandukaWeerasekara
i did the same thing what u guys explain above to retrieve the image from database but unfortunately it is not displaying in imagecell... it binds and displaying me productname and Description as text and detail respactively but the issue is not showing the image... if anyone can help me out thanks