Skip to main content Skip to footer

Load Images in C1DataGrid for Silverlight using WCF

More often than not, users have a requirement to display images in Silverlight applications. Here, we discuss the same using C1DataGrid for Silverlight. To begin with, lets create a Silverlight project, add a Wcf service to the web project and name it 'WCFService'. Then create a class decorated with 'DataContract' attribute. Create another class, with a property decorated with 'OperationContract' attribute, that creates connection with the database and gets data. Here's the code to be added to the service in web project:


namespace WCFImages.Web  
{  
 [ServiceContract(Namespace = "")]  
 [SilverlightFaultBehavior]  
 [AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]  
 public class WCFService  
 {  
  [OperationContract]  
  public ImageEmployee[] GetAllEmp()  
  {  
   string \_path = HttpContext.Current.Server.MapPath(@"~\\App\_Data\\NWind.mdb");  
   OleDbConnection Conn = new OleDbConnection("Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" + _path + ";Persist Security Info=False;");  
   Conn.Open();  
   OleDbCommand Cmd = new OleDbCommand("Select EmployeeID, LastName, FirstName, Title, City, Country, Photo  from Employees", Conn);  
   OleDbDataReader Reader = Cmd.ExecuteReader();  

   ImageEmployee[] arrEmp = new ImageEmployee[9];  
   int count = 0;  
   while (Reader.Read())  
   {  
    var employee = new ImageEmployee();  
    employee.EmployeeID = Reader.GetInt32(0);  
    employee.LastName = Reader.GetString(1);  
    employee.FirstName = Reader.GetString(2);  
    employee.Title = Reader.GetString(3);  
    employee.City = Reader.GetString(4);  
    employee.Country = Reader.GetString(5);  

    byte[] blob = new byte[(Reader.GetBytes(6, 0, null, 0, int.MaxValue))];  
    Reader.GetBytes(6, 0, blob, 0, blob.Length);  

    using (var ms = new MemoryStream())  
    {  
     ms.Write(blob, 78, blob.Length - 78);  
     Bitmap bmp = (Bitmap)Image.FromStream(ms);  
     using (var msJpg = new MemoryStream())  
     {  
      bmp.Save(msJpg, ImageFormat.Jpeg);  
      employee.Photo = msJpg.GetBuffer();  
     }  
    }  

    arrEmp[count] = employee;  
    count++;  
   };  
   Conn.Close();  
   return arrEmp;  
  }  
 }  

[DataContract]  
public class ImageEmployee  
{  
 [DataMember]  
 public int EmployeeID { get; set; }  
 [DataMember]  
 public string LastName { get; set; }  
 [DataMember]  
 public string FirstName { get; set; }  
 [DataMember]  
 public string Title { get; set; }  
 [DataMember]  
 public string City { get; set; }  
 [DataMember]  
 public string Country { get; set; }  
 [DataMember]  
 public byte[] Photo { get; set; }  
 }  
}  

To the Silverlight project, add the following class that implements the IValueConverter interface. The ‘Convert’ method reads a byte array and converts it into a memory stream. This memory stream is then bound to the ‘BitmapImage’ so that it can be further bound with the Image UI element.


public class ImageConverter : IValueConverter  
{  
 public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)  
 {  
  var imageBytes = (byte[])value;  
  MemoryStream memStream = new MemoryStream(imageBytes, false);  
  BitmapImage _image = new BitmapImage();  
  _image.SetSource(memStream);  
  return _image;  
 }  

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

Now, some design. Here's the entire xaml:


<UserControl.Resources>  
  <src:ImageConverter x:Key="ImageConverter"/>  
</UserControl.Resources>  
<Grid x:Name="LayoutRoot" Background="White">  
 <c1:C1DataGrid AutoGenerateColumns="False" Name="c1DataGrid1" CanUserAddRows="False" RowHeight="60" >  
   <c1:C1DataGrid.Columns>  
     <c1:DataGridBoundColumn Header="EmployeeID" Binding="{Binding EmployeeID}" Width="80"/>  
     <c1:DataGridBoundColumn Header="LastName" Binding="{Binding LastName}" Width="80"/>  
     <c1:DataGridBoundColumn Header="FirstName" Binding="{Binding FirstName}" Width="80"/>  
     <c1:DataGridBoundColumn Header="Title" Binding="{Binding Title}" Width="140"/>  
     <c1:DataGridBoundColumn Header="City" Binding="{Binding City}" Width="80"/>  
     <c1:DataGridBoundColumn Header="Country" Binding="{Binding Country}" Width="80"/>  
     <!--DataGridImageColumn to display images-->  
     <c1:DataGridImageColumn Header="Photo" Binding="{Binding Photo,Converter={StaticResource ImageConverter}}" Width="80"/>  
   </c1:C1DataGrid.Columns>  
  </c1:C1DataGrid>  
</Grid>  

Finally, we need to bind the grid. Lets add a Wcf service reference to the the xaml.cs page, name it 'ImageService' and add following code :


public partial class MainPage : UserControl  
{  
 public MainPage()  
 {  
  InitializeComponent();  
  var client = new WCFServiceClient();  
  client.GetAllEmpCompleted += (s, e) =>  

  {  
   c1DataGrid1.ItemsSource = e.Result;  
  };  

  client.GetAllEmpAsync();  
 }  
}  

Here's a screenshot of the grid with images being displayed in a DataGridImageColumn. screenshot Download C# Sample Download Vb.Net Sample

MESCIUS inc.

comments powered by Disqus