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. Download C# Sample Download Vb.Net Sample